Доступ к значениям неизвестных типов полей при использовании entity_metadata_wrapper

12

Я пытался использовать классы Entity Metadata Wrapper (определенные модулем entity в Drupal 7) для доступа к значениям полей, так как это кажется чистым способом сделать это.

Однако есть пара вещей, которые делают это немного неловким. Предположим, у меня есть оболочка для типа контента, который определяет поле с таким именем field_something:

$wrapper = entity_metadata_wrapper('node', node_load($nid));
$value = $wrapper->field_something->value();

Первая проблема, с которой я столкнулся, заключается в том, что у меня нет возможности узнать заранее, является ли то, что я получаю, фактическим значением (строка, сущность и т. Д.), Другой оболочкой структуры метаданных (когда поля имеют несколько значений) или массивом (когда поля имеют несколько свойств).

Я нашел способ ответить на эти вопросы, используя info()метод:

$info = $wrapper->field_something->info();
$is_multi_value = (strpos($info['type'], 'list<') === 0);
$has_multiple_properties = isset($info['property info']]);

Однако это вряд ли практично. Всякий раз, когда я хочу использовать поле, не зная его определения, я должен учитывать несколько случаев. Это делает мой код довольно тяжелым.

Чтобы справиться с этим, я написал код, который:

  1. Гарантирует, что мы всегда возвращаем массив, даже если это одно поле значения;
  2. Если имеется несколько свойств, вернуть значение первого столбца.

Пункт 1. здесь всегда будет работать, если только вызывающая сторона не хочет знать, было ли это поле с одним значением или нет. Пункт 2 работает в некоторых случаях, но не во всех, но удобен, когда он применяется.

Вот код:

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;
}

Поэтому мой вопрос: существуют ли более простые / лучшие способы решения этой проблемы получения значений из оболочки метаданных, когда тип поля неизвестен?

Алиса Хитон
источник

Ответы:

4

Вот несколько предложений, чтобы сделать этот процесс немного проще.

$wrapper->field_something->type();

возвращает тип поля, то есть node, taxonomy_term, integer, и textт.д. Затем можно обработать значение , возвращенное $wrapper->field_something->value()правильно.

Также

$wrapper->field_something->raw()

вернет необработанное значение поля. Который будет либо arrayв случае многозначных полей только значения. Например, entity_referenceбудет nid(или идентификатором сущности) ссылочной сущности или arrayидентификаторами ссылочной сущности.

thepearson
источник
Ой, я вошел в это слишком быстро! Я хотел добавить: $ wrapper-> field_something-> type () возвращает ту же информацию, что и элемент 'type' массива, возвращаемого $ wrapper-> field_something-> info (). Важно, что он по-прежнему возвращает строку «список <тип>» для многозначных типов, поэтому мне все еще нужен strpos (или эквивалентный), чтобы определить его многозначность (если я хочу разобраться с ним перед извлечением).
Алиса Хитон,
Что касается второго пункта: я действительно могу решить, является ли он многозначным, проверяя возвращение -> raw () или - - value (), однако я бы предпочел знать, прежде чем извлекать значение, как если бы оно было многозначным, тогда Я хочу запустить его через цикл foreach с помощью -> getIterator (), а не вручную проходить через массив, который требует от меня повторного создания оболочки для каждого элемента.
Алиса Хитон,
3

Так как никто не предложил другого решения, я отвечу на свой вопрос:

Там является не более простым способом доступа к значениям неизвестных типов полей при использовании оберток метаданных объекта.

Существуют альтернативные методы, которые я изначально описал (например, те, на которые указал @thepearson). В частности, этот метод полезен:

 entity_property_list_extract_type($type)

Он вернет перечисленный тип, если ваш тип является списком (например, 'integer', если ваш тип 'list <integer>'), или false, если ваш тип не является списком. Внутренне это делает strpos точно так же, как код, который я первоначально разместил, но я предполагаю, что это - больше будущего.

Вывод таков:

  • Оболочки метаданных сущностей работают хорошо, если вы не имеете представления о типах полей и хотите тщательно рассмотреть каждый возможный случай;

  • Оболочки метаданных сущностей работают хорошо, если вы точно знаете, какие типы имеют ваши поля, и хотите их использовать;

  • Если у вас есть только некоторые представления о том, на что похожи ваши типы полей (например, весь текст, но вы не знаете, отформатированы они или нет, и вы не знаете, являются ли они однозначными или многозначными), тогда обертки метаданных Entity не предоставляйте ярлыки, и вам нужно написать свое собственное, как я сделал в первоначальном вопросе.

Алиса Хитон
источник
1

Для проверки одного / нескольких полей я нашел полезным проверить тип объекта-оболочки, который будет EntityListWrapperдля поля с несколькими значениями и EntityValueWrapperдля поля с одним значением:

<?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
источник
Или дажеif($wrapper->field_name instanceof EntityListWrapper) {...}
rudolfbyker