Я пытался использовать классы 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 работает в некоторых случаях, но не во всех, но удобен, когда он применяется.
Вот код:
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;
}
Поэтому мой вопрос: существуют ли более простые / лучшие способы решения этой проблемы получения значений из оболочки метаданных, когда тип поля неизвестен?
Так как никто не предложил другого решения, я отвечу на свой вопрос:
Там является не более простым способом доступа к значениям неизвестных типов полей при использовании оберток метаданных объекта.
Существуют альтернативные методы, которые я изначально описал (например, те, на которые указал @thepearson). В частности, этот метод полезен:
Он вернет перечисленный тип, если ваш тип является списком (например, 'integer', если ваш тип 'list <integer>'), или false, если ваш тип не является списком. Внутренне это делает strpos точно так же, как код, который я первоначально разместил, но я предполагаю, что это - больше будущего.
Вывод таков:
Оболочки метаданных сущностей работают хорошо, если вы не имеете представления о типах полей и хотите тщательно рассмотреть каждый возможный случай;
Оболочки метаданных сущностей работают хорошо, если вы точно знаете, какие типы имеют ваши поля, и хотите их использовать;
Если у вас есть только некоторые представления о том, на что похожи ваши типы полей (например, весь текст, но вы не знаете, отформатированы они или нет, и вы не знаете, являются ли они однозначными или многозначными), тогда обертки метаданных Entity не предоставляйте ярлыки, и вам нужно написать свое собственное, как я сделал в первоначальном вопросе.
источник
Для проверки одного / нескольких полей я нашел полезным проверить тип объекта-оболочки, который будет
EntityListWrapper
для поля с несколькими значениями иEntityValueWrapper
для поля с одним значением:источник
if($wrapper->field_name instanceof EntityListWrapper) {...}