УрокКорректная работа с полями в седьмом Друпале. Entity metadata wrappers.
В седьмой версии Друпала вывод полей был несколько изменён в связи с усовершенствованием многоязычной системы. Если раньше для вывода содержимого поля достаточно было написать так:
print $node->field_name[0]['value'];
то в семёрке добавился к полю ещё и язык (для одноязычных сайтов по умолчанию 'und' - undefined, константа LANGUAGE_NONE):
print $node->field_name[LANGUAGE_NONE][0]['value'];
Вывод значение поля стал чуть длиннее. Но если бы это было единственной проблемой - тогда и проблем бы не было :) Но здесь в игру вступают мультиязычные сайты. И получается, что если сайт наш англоязычный например, а мы пользовались кодом выше, то значение поля теперь получить не удастся, т.к. теперь надо его получать иначе:
print $node->field_name['en'][0]['value'];
На первый взгляд - беда, товарищи. Однако не всё так плохо, как казалось на первый взгляд: есть функция field_language(), которая способна возвращать код текущего языка поля. А дальше полученный код можно уже подставить при получении значения:
$lang = field_language('node', $node, 'field_name'); print $node->field_name[$lang][0]['value'];
Уже лучше - такой код поможет избежать коллапса при смене языка сайта. Однако дальше - лучше. В ядре нашлась ещё одна полезная функция field_get_items(). Она возвращает массив из всех значений поля. Например, если в поле только одно значение, то пользоваться ей так:
$field_values = field_get_items('node', $node, 'field_name'); print $field_values[0]['value'];
Если же количество значений больше одного, то можно их выводить циклом:
$field_values = field_get_items('node', $node, 'field_name'); foreach ($field_values as $field) { print $field['value']; }
В принципе, второй вариант является более общим, т.к. работает и для случая с одним значением поля.
На самом деле, на этом можно было бы даже остановиться, однако не рассказать о возможностях Entity API для работы с полями было бы крайне неправильно. Итак,
Возможности Entity API по работе с полями
В этом модуле есть великолепная функция entity_metadata_wrapper(). Она возвращает объект, который является удобной обёрткой для вывода и изменения данных объекта вместе с его полями. Например, значение поля можно получить так:
$wrapper = entity_metadata_wrapper('node', $node); print $wrapper->field_name->value();
Если же значений несколько, то можно воспользоваться такой конструкцией:
$wrapper = entity_metadata_wrapper('node', $node); foreach ($wrapper->field_name as $field) { print $field->value(); }
Пример из README.txt модуля Entity API (получаем емейл автора материала):
$wrapper = entity_metadata_wrapper('node', $node); $wrapper->author->mail->value();
Если вы хотите получить значение поля, которое может быть безопасно выведено на экран, то передайте в value() атрибут 'sanitize', установленный в TRUE (в этом случае все тэги будут выведены в виде текста).
print $wrapper->field_name->value(array('sanitize' => TRUE));
Также существует атрибут 'decode', который отвечает за раскодирование всех HTML сущностей поля и вырезание тэгов из текста:
print $wrapper->body->value->value(array('decode' => TRUE));
Если же вам понадобятся данные без обработки в том виде, в котором их ввёл пользователь, тогда воспользуйтесь таким методом:
print $wrapper->body->value->raw();
Ещё одной отличительной особенностью этого подуля является автоматическое определение полей, которые ссылаются на другую сущность. Например, если у вас поле ссылается на другой материал, то вы на лету можете использовать объект этого материала:
$wrapper = entity_metadata_wrapper('node', $node); // Выведем заголовок материала, на которое ссылается поле. print $wrapper->field_some_relation->value()->title;
Отдельно стоит отметить, что $wrapper->field_name - это и массив и объект одновременно. То есть вы можете использовать его как объект ($wrapper->field_name->value()
) или как массив ($wrapper->field_name[0]
). Говоря техническим языком, он реализует интерфейсы IteratorAggregate, ArrayAccess и Countable.
Ещё одна важная деталь, на которую можно было не обратить внимание: entity_metadata_wrapper() даёт доступ не только к полям, но и к самим сущностям. Поэтому если вы загрузили сущность через entity_metadata_wrapper(), вы можете продолжать с ней работать:
$node = node_load(123); $wrapper = entity_metadata_wrapper('node', $node); $wrapper->title = 'New title for the node'; $wrapper->save();
При использовании обёрточного класса из модуля Entity API есть один недостаток - поле будет отображаться через entity_metadata_wrapper() только в том случае, если поле было описано через hook_entity_property_info(). Все поля ядра и наиболее популярные поляиз контриб-модулей поддерживают такую обёртку, однако среди множества модулей можете наткнуться на всякое, поэтому не стоит об этом забывать.
Вдохновение черпал отсюда: http://pixeljets.com/blog/writing-robust-code-uses-fields-drupal-7.
- Spleshka
- 01.05.2012
- 27319
Комментарии
Извиняюсь за, может быть, глупый вопрос, но что писать вместо 'value' в строчке:
print $node->field_name[LANGUAGE_NONE][0]['value'];
?
В зависимости от типа поля, вместо 'value' может быть например 'tid', 'nid' и так далее. Хотя для текстовых полей именно 'value' работает. Какое у вас поле?
У меня текстовое, field_tags, с 'value' не работает, только так как я описал ниже
у меня в 7.12 получилось вывести поле только вот так:
print $node->field_name[LANGUAGE_NONE][0]['taxonomy_term']->name;
привет! вопрос есть - как обратиться правильно к чекбоксу в семерке? пишу так
те мне надо проверить статус чекбокса при сохранении формы.
Спасибо
Добрый день. Пытаюсь получить число из поля при помощи передачи его через URL, написал код на ссылку
<a href="<?php print base_path(); ?>&<? php print field_r_price[0]['value']; ?>forma-zakaza.html?product=<?php print drupal_get_title();?>&price=<?php print field_get_items('node', node_load(8), 'field_r_price');?> ">заказать товар</a>
но выдает ошибку на страничке вместо ссылки. Необходимо как понятно одно значение. Что посоветуете, как быть?
Ошибка здесь (№1):
И здесь (№2):
Функция field_get_items() возвращает массив. Вам надо сначала:
А потом уже выводить
$items[0]['value'];
в качестве значения поля.А вот это
где писать? я в значении по умолчанию в поле пишу %get[$item], мне вместо него вставлять?
так чтоли?
<a href="<?php print base_path(); ?>&<?php print field_get_items('node', node_load(8), 'field_r_price');?>forma-zakaza.html?product=<?php print drupal_get_title();?>&price=<<? php print $node->field_r_price[LANGUAGE_NONE][0]['value']; ?> ">заказать товар</a>
Переменная передает массив, по %get[name_item] выдает Array, не могу понять как вывести значение поля.У меня там простая цена указана..
Вобщем так и не понял куда лепить вот это
$items[0]['value']
поэтому стал передавать значение явно, т.е. прописывая его в запросе. К сожалению так и не дождался ответа..@1541, вам сначала php надо подучить...
<?php print $items[0]['value']; ?>
надо писать вместо :<?php print field_get_items('node', node_load(8), 'field_r_price');?>
<?php print field_r_price[0]['value']; ?>
Спасибо большое. С ПХП я и правда не дружен. Вот докачиваю урок от "Специалист" и Бойко. Какой лучше посоветуете? Ваш вариант сейчас попробую.
что то я совсем уж наверное тугодум. сделал как Вы сказали, получил конструкцию вида:
<a href="<?php print base_path(); ?>&pric=<?field_get_items('node', node_load(8), 'field_r_price');?>forma-zakaza.html? product=<?php print drupal_get_title();?>& price=<?php print pric[0]['value']; ?>">заказать товар</a>
на что браузер мне пишет: Parse error: syntax error, unexpected '[' in Z:\home\art1\www\modules\php\php.module(80) : eval()'d code on line 3. Наверняка надо как то иначе мне это вставлять, только ума не приложу как.
Перечитал еще раз статью и понял что и как.. Благодаря Вашим подсказкам:) Получил конструкцию вида:
<a href="<?php print base_path(); ?>forma-zakaza.html? product=<?php print drupal_get_title();?>& price=<?php $items = field_get_items('node', node_load(8), 'field_r_price'); print $items[0]['value']; ?> ">заказать товар</a>
Все здорово, переменная передалась, спасибо Вам большое.
Добрый день. Не могу вывести значение поля в шаблоне node--event.tpl, просто ничего не выводиться, как-будто из этого шаблона нет доступа к полям. Вот код которым пробую это сделать:
$node = node_load($nid);
print ($node->field_event_date['und'][0]['value']);
print ($node->field_event_date['und'][0]['value2']);
$date_values = field_get_items('node', $node, 'field_event_date');
print ($date_values[0]['value']);
print ($date_values[0]['value2']);
Но не ошибок, не значений не выводиться. Можете подсказать, делаю на друпал 7
Первая строка некорректна, в шаблоне node.tpl.php объект $node уже есть. Последние строки тоже лишние.
Да, спасибо за ответ.
Заработало. Действительно убрал $node = node_load($nid);.
Но странность в том, что заработало сначала print ($node->field_event_date[0]['value']); - без ['und'] , работало какое-то время, даже написал небольшую логику обработки этих дат, потом перестало. Добавил ['und'] и снова заработало.
Кто подскажет, как получить все возможные значения поля? Например у поля типа список.
В базе они хранятся в content_node_field -> global_settings
Комментировать