Zastanawiałem się nad wykorzystaniem klas opakowania encji metadanych (zdefiniowanych przez moduł encji w Drupal 7), aby uzyskać dostęp do wartości pól, ponieważ wydaje się, że jest to czysty sposób.
Jest jednak kilka rzeczy, które sprawiają, że jest to trochę niezręczne. Załóżmy, że mam opakowanie dla typu zawartości, który definiuje pole o field_something
takiej nazwie :
$wrapper = entity_metadata_wrapper('node', node_load($nid));
$value = $wrapper->field_something->value();
Pierwszym problemem, jaki mam, jest to, że nie mam możliwości wcześniejszego sprawdzenia, czy otrzymuję rzeczywistą wartość (ciąg, encję itp.), Inne opakowanie struktury metadanych (gdy pola mają wiele wartości) lub tablicę (kiedy pola mają wiele właściwości).
Znalazłem sposób na udzielenie odpowiedzi na te pytania przy użyciu info()
metody:
$info = $wrapper->field_something->info();
$is_multi_value = (strpos($info['type'], 'list<') === 0);
$has_multiple_properties = isset($info['property info']]);
Nie jest to jednak praktyczne. Ilekroć chcę użyć pola, nie znając wcześniej jego definicji, muszę wziąć pod uwagę kilka przypadków. To sprawia, że mój kod jest dość ciężki.
Aby sobie z tym poradzić napisałem kod, który:
- Zapewnia, że zawsze otrzymujemy tablicę, nawet jeśli jest to pole o pojedynczej wartości;
- Jeśli istnieje wiele właściwości, zwróć wartość pierwszej kolumny.
Punkt 1. tutaj zawsze będzie działał, chyba że dzwoniący chce wiedzieć, czy było to jedno pole wartości, czy nie. Punkt 2 działa w niektórych przypadkach, nie we wszystkich, ale jest wygodny, gdy ma zastosowanie.
Oto kod:
function entity_metadata_simple_values($field) {
$fields = array();
$values = array();
$info = $field->info();
if (strpos($info['type'], 'list<') === 0) {
foreach ($field->getIterator() as $field_iteration) {
$fields[] = $field_iteration;
}
} else {
$fields[] = $field;
}
foreach ($fields as $final_field) {
$ff_info = $final_field->info();
if (isset($ff_info['property info'])) {
$column = reset(array_keys($ff_info['property info']));
$values[] = $final_field->{$column}->value();
} else {
$values[] = $final_field->value();
}
}
return $values;
}
Moje pytanie brzmi zatem: czy istnieją prostsze / lepsze sposoby rozwiązania tego problemu pobierania wartości z opakowania metadanych, gdy typ pola nie jest znany?
Ponieważ nikt nie wymyślił innego rozwiązania, odpowiem na własne pytanie:
Nie ma prostszego sposobu uzyskiwania dostępu do wartości nieznanych typów pól podczas korzystania z opakowań metadanych encji.
Istnieją metody alternatywne do tych, które początkowo opisałem (na przykład te wskazane przez @ thepearson). W szczególności ta metoda jest przydatna:
Zwróci wymieniony typ, jeśli typ jest listą (np. „Liczba całkowita”, jeśli typ jest „list <liczba całkowita>”), lub false, jeśli typ nie jest listą. Wewnętrznie robi StrPos, tak jak kod, który pierwotnie opublikowałem, ale myślę, że jest to bardziej przyszłościowe.
Wniosek jest taki, że:
Opakowania metadanych encji działają dobrze, jeśli nie masz pojęcia o typach pól i chcesz dokładnie zająć się każdym możliwym przypadkiem;
Opakowania metadanych encji działają dobrze, jeśli dokładnie wiesz, jakie są typy pól i chcesz z nich korzystać;
Jeśli masz tylko kilka pomysłów na to, jakie są typy pól (na przykład cały tekst, ale nie wiesz, czy są one sformatowane, czy nie, i nie wiesz, czy są one jedno- lub wielowartościowe), to otoki metadanych encji nie udostępniaj żadnych skrótów i musisz napisać własny, tak jak ja w pierwszym pytaniu.
źródło
Przy sprawdzaniu pojedynczego / wielu pól uznałem za przydatne przetestowanie typu obiektu opakowania, który będzie
EntityListWrapper
dla pola o wielu wartościach iEntityValueWrapper
dla pola o jednej wartości:źródło
if($wrapper->field_name instanceof EntityListWrapper) {...}