Правильно выводим поля в Drupal 7

Drupal 7 дает возможность работать с сущностями (Entities), а вместе с этим и мощный API для работы с полями, которые могут быть прикреплены к сущностям. Если Вы управляете полями через вкладки «Управление полями» и «Управление отображением» на странице типов материалов, то Drupal сам заботится о правильной работе с полями.

Однако, мы часто сталкиваемся с необходимостью отображения поля вне сущности. Типичным примером может быть отображение данных о авторе ноды в боковой колонке сайта. Конечно, такие модули, как Panels и CCK Blocks могут делать это самостоятельно, но сделать это вручную не так уж и сложно.

Возможно, Вы видели (или писали) код, который выглядит примерно так:

  1. // Это неверный пример
  2. $block['content'] = $node->field_name['und'][0]['safe_value'];

Копание в объекте ноды было довольно распространено в Drupal 6, и «safe_value» казалось бы, поможет избежать возможных проблем. Что в этом плохого? Давайте рассмотрим.

  1. Во-первых, элемент ['und'] является частью локализации поля в Drupal 7; прямой доступ к его значению приведет к проблемам в любой многоязычной среде. 
  2. Получая доступ напрямую к значению поля, мы теряем возможность темизировать рендер поля и использовать базовую разметку.
  3. [0] [safe_value] явно обращается к первому значению поля — если вы хотите использовать каждое значение из нескольких значений поля — придется использовать цикл.
  4. Некоторые поля (например, node references) не имеют элемента safe_value, только value, — которые могут быть легко отображены без соответствующей предобработки. Это опасно, и не только потому, что node references содержит опасные данные (тот же nid), но и потому, что это вредная привычка привычка, особенно для новых разработчиков. Использование value других типов полей также может быть очень опасно.

Как сделать правильно? Использовать field_view_field()!

В чем профит?

Эта функция вернет очищенные значения (фикс 4) поля в полном объеме (фикс 3) на текущем языке (фикс 1) и в формате массива, готового к рендерингу, поэтому вы получите все связанные данные с разметкой (фикс 2). Победа! Если поле не имеет значения, функция будет использовать резервные участки языка логики, доступные для текущего языка. Вы также можете передать массив вариантов форматирования или задать режим просмотра в качестве дополнительного аргумента функции.

Рассмотрим пример:

  1. <?php
  2. $nid = node_load('nid');
  3. $output = field_view_field('node', $nid, 'field_name', array(
  4. 'label'=>'hidden',
  5. 'settings' => array('image_style' => 'front_models')));
  6. print render($output);
  7. ?>

Пояснения:

  1. загружаем в переменную $nid содержимое ноды с номером 'nid'
  2. загружаем в переменную $output массив выдаваемый функцией field_view_field, здесь 'node' — тип сущности, 'field_name' — имя поля, которое хотим вывести, далее в массиве мы передаем настройки для отображения: скрываем заголовок, и поскольку тип поля — картинка, то выбираем для нее стиль отображения — front_models (его мы создали отдельно «конфигурация -- мультимедия -- стили изображения»)
  3. выводим значение массива отрендерив его механизмами drupal

Для поля body доступные еще вот такие настройки вывода

  1. 'type' => 'text_summary_or_trimmed',
  2. 'settings'=>array('trim_length' => 150),

Если нужно использовать форматтер, отличный от родного, то укажите вот так:

  1. $display = array('type' => 'my_formatter');
  2. $output = field_view_field('node', $node, 'field_foo', $display);

Если нужно загрузить поле из термина таксономии, то используйте типа сущности taxonomy_term и грузите ее с помощью taxonomy_term_load ($tid)

Для термина таксономии type может принимать значения:

  • taxonomy_term_reference_link — имя термина как ссылка
  • taxonomy_term_reference_plain — имя термина как простой текст

Еще один вариант вывода, удобен для отображения какого то конкретного значения для множественного поля:

$fields = field_get_items('node', $node, 'field_name');

Здесь мы на выходе получаем массив значений полей, в каждом из них присутствует value, format и safe_value.

Если сюда добавить следующее, то получим уже отрендеренный результат, где дельта — это значение индекса поля, начиная с нуля

  1. $output = field_view_value('node', $node, 'field_name', $field[$delta]);
  2.  
  3. //пример
  4.  
  5. $node = node_load($nid);
  6. $image = field_get_items('node', $node, 'field_image');
  7. $output = field_view_value('node', $node, 'field_image', $image[0], array(
  8.   'type' => 'image',
  9.   'settings' => array(
  10.     'image_style' => 'thumbnail',
  11.     'image_link' => 'content',
  12.   ),
  13. ));