Dostęp do wartości nieznanych typów pól podczas korzystania z podmiotu_metadanych_wrapper

12

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_somethingtakiej 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:

  1. Zapewnia, że ​​zawsze otrzymujemy tablicę, nawet jeśli jest to pole o pojedynczej wartości;
  2. 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?

Alice Heaton
źródło

Odpowiedzi:

4

Oto kilka sugestii, które ułatwią ten proces.

$wrapper->field_something->type();

powróci typ pola, to znaczy node, taxonomy_term, integer, textitd. Następnie można obsłużyć wartość zwracana z $wrapper->field_something->value()prawidłowo.

Również

$wrapper->field_something->raw()

zwróci surową wartość pola. Który będzie albo arrayw przypadku wielu wartości pól o tej samej wartości. Na przykład an entity_referencebędzie nid(lub identyfikatorem encji) przywoływanej encji lub arrayidentyfikatorem encji referencyjnej.

thepearson
źródło
Ups, wszedłem w to zbyt szybko! Chciałem dodać: $ wrapper-> field_something-> type () zwraca te same informacje, co element „type” tablicy zwrócony przez $ wrapper-> field_something-> info (). Co najważniejsze, nadal zwraca ciąg „list <typ>” dla typów wielowartościowych, więc wciąż potrzebuję strpos (lub odpowiednika), aby ustalić, czy jest wielowartościowy (jeśli chcę to wypracować przed pobraniem).
Alice Heaton,
Co do drugiego punktu: naprawdę mogę się dowiedzieć, czy jest on wielowartościowy, testując zwrot z -> raw () lub - - value (), ale wolałbym wiedzieć przed pobraniem wartości, tak jakby to była wielowartościowa Chcę uruchomić go za pomocą pętli foreach za pomocą -> getIterator (), a nie ręcznie przechodzić przez tablicę, która wymaga ode mnie ponownego utworzenia opakowania dla każdego elementu.
Alice Heaton
3

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:

 entity_property_list_extract_type($type)

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.

Alice Heaton
źródło
1

Przy sprawdzaniu pojedynczego / wielu pól uznałem za przydatne przetestowanie typu obiektu opakowania, który będzie EntityListWrapperdla pola o wielu wartościach i EntityValueWrapperdla pola o jednej wartości:

<?php
...
$wrapper = entity_metadata_wrapper('user', $account);
// Get address, or first address if a multi-value field instance.
if (get_class($wrapper->field_address) == 'EntityListWrapper') {
  $value = $wrapper->field_address[0]->value();
}
else {
  $value = $wrapper->field_address->value();
}
Fonant
źródło
Lub nawetif($wrapper->field_name instanceof EntityListWrapper) {...}
Rudolfbyker