УрокРендер массивов в седьмом Друпале
Рендерные массивы являются строительными блоками страницы Drupal, начиная с седьмого Друпала. Рендерный массив - это ассоциативный массив, который соответствует стандартам и структуре данных, используемых в системе рендеринга Друпала.
Данные, используемые для создания страницы (и всех ее частей), хранятся в виде структурированных массивов до этапа рендеринга в системе темизации. Это дает возможность с легкостью менять разметку или содержание страницы и обеспечивает повышение производительности в будущем.
Что такое рендер?
Касательно Друпала, рендер обозначает преобразование рендер массивов в HTML код.
Что такое рендер массив?
Рендер массив – классический структурированный массив в Drupal, который предоставляет информацию/данные (возможно, вложенную) наряду с подсказками относительно того, как этот элемент должен быть представлен (например, #type определяет тип элемента).
Массив страницы может выглядеть следующим образом:
$page = array( '#show_messages' => TRUE, '#theme' => 'page', '#type' => 'page', 'content' => array( 'system_main' => array(...), 'another_block' => array(...), '#sorted' => TRUE, ), 'sidebar_first' => array( ... ), 'footer' => array( ... ), ... );
Для чего это делается?
До выхода Друпал 7 можно было запросто изменять формы (с помощью hook_form_alter()), однако остальные элементы, которые можно было изменять в модулях или темах, превращались в HTML код до того, как передавались для изменений.
Начиная с седьмого Друпала модуль или тема может использовать hook_page_alter(), чтобы изменить структуру или содержание страницы в самый последний момент. Это означает, что несколько строк PHP кода в теме могут разместить блок в том месте страницы, где вам это необходимо.
Изменение элементов
После выхода седьмого Друпала блоки и страницы могут быть изменены так же, как раньше мы меняли формы. Многие другие элементы также стали доступны для изменения. Например, с помощью hook_page_alter() вы можете в своём модуле или теме сделать так:
function ИМЯМОДУЛЯ_page_alter(&$page) { // Пененосим форму поиска из левой колонки в футер $page['footer']['search_form'] = $page['sidebar_first']['search_form']; unset($page['sidebar_first']['search_form']); // Убираем блок "Powered by Drupal" unset($page['footer']['system_powered-by']); }
Как рендерные массивы связаны с элементами?
В модулях можно определять новые элементы, которые на самом деле являются рендерными массивами, записанными по определённым правилам. Для этого используется hook_element_info(). Элемент – это рендерный массив, который имеет #type и другие свойства, определяющие его дальнейшее поведение. Когда создаётся рендерный массив и ему задан #type, то к нему подгружаются значения по умолчанию для тех атрибутов, которых нет в массиве, но они описаны в hook_element_info() для этого элемента.
Создание данных в виде рендерных массивов
В Drupal 7, в отличие от прошлых версий, модуль практически всегда создает данные в виде рендерных массивов. Функция вызова любой страницы возвращает массив, который в дальнейшем будет отрендерен (превращён в HTML). Это позволяет модулям хранить данные в массивах настолько долго, насколько это возможно в процессе создания страницы.
В Drupal 6 использовался метод рендеринга данных и их сбора в виде HTML:
function mymodule_menu() { $items['mypage-html'] = array( 'title' => 'Страница с функцией возвращающей HTML', 'page callback' => 'mymodule_html_page', 'access callback' => TRUE, ); $items['mypage-ra'] = array( 'title' => 'Страница возвращающая рендерный массив', 'page callback' => 'mymodule_ra_page', 'access callback' => TRUE, ); return $items; } // Старый метод, который возвращает html код. // Кстати, он ещё работает в седьмом Друпале. function mymodule_html_page { $output = '<p>A paragraph about some stuff...</p>'; $output .= '<ul><li>first item</li><li>second item</li><li>third item</li></ul>'; return $output; } // Новый метод, который возвращает рендерный массив function mymodule_ra_page { $output = array( 'first_para' => array( '#type' => 'markup', '#markup' => '<p>A paragraph about some stuff...</p>', ), 'second_para' => array( '#items' => array('first item', 'second item', 'third item'), '#theme' => 'item_list', ), ); return $output; }
Примеры массивов разных типов
Как и раньше, все элементы Drupal (см. hook_element_info(), который был hook_elements() в Drupal 6) представляют собой описанный тип данных. Глядя на system_element_info(), мы видим множество предопределенных типов, в том числе page, form, html_tag, value, markup, link, fieldset и многие другие. По соглашению, #- атрибуты, используемые этим типом, документируются с соответствующей функцией темизации. Таким образом, например, атрибуты, используемые в элементе типа #type => 'html_tag' можно найти в функции theme_html_tag().
Вот три примера из модуля Examples (Render example):
$demos = array( t('Super simple #markup') => array( '#markup' => t('Some basic text in a #markup (shows basic markup and how it is rendered)'), ), 'prefix_suffix' => array( '#markup' => t('This one adds a prefix and suffix, which put a div around the item'), '#prefix' => '<div><br/>(prefix)<br/>', '#suffix' => '<br/>(suffix)</div>', ), 'theme for an element' => array( 'child' => array( t('This is some text that should be put together'), t('This is some more text that we need'), ), '#separator' => ' | ', '#theme' => 'render_example_aggregate', ), );
Примеры типов элементов
К рендерному массиву можно применить множество уже существующих типов или создать свои. Ниже приведены самые распространенные.
Обратите внимание, что многие из этих свойств описаны в Forms API, потому что в Forms API всегда использовались рендерное API для указания типов, но они не были задокументированы как типы рендерного API, коими они, несомненно, являются в Drupal 7.
#type | Тип элемента. Если массив – элемент, то свойства элемента будут загружены по умолчанию. Это ведет к сокращению набора предопределенных свойств, которые могут быть взяты из описания этого элемента в hook_element_info(). |
#markup | Простейшее свойство, которое просто создает строку с разметкой #type => 'markup'. По сути, с его помощью можно просто вставить кусок HTML’a без каких-либо преобразований или дальнейшего рендера. |
#prefix/#suffix | Используется при необходимости добавить строку (или разметку) в начале или в конце элемента. |
#pre_render | Массив функций, который может изменить рендерный массив перед вызовом рендера для него. Это свойство может изменить, удалить части, установить #printed = TRUE, чтобы предотвратить последующий рендер и т.д. |
#post_render | Массив функций, который может обрабатывать HTML, полученный в результате рендера элемента. По большому счету это тоже самое, что и #theme_wrappers, за исключением того, что не используется система темизации. |
#theme | Набор хуков темы, которые полностью ответственны за рендер элементов массива (включая дочерние). Примечание: на самом деле, #theme в Drupal 7 и #theme в Drupal 6 не связаны между собой. Обычно, #theme' => 'function_name' вызывает функцию вида theme_function_name(), а остальные значение массива передаются в эту функцию в качестве аргументов. Вот список всех дефолтных хуков темы: http://api.drupal.org/api/drupal/modules--system--theme.api.php/group/themeable/7 |
#theme_wrappers | Массив функций темы, который имеет возможность добавлять что-либо к рендерному массиву после того, как дочерние элементы были отрендерены и помещены в #children. Обычно используется для добавления HTML вокруг отрендереных дочерних элементов, особенно если дочерние элементы были отрендерены рекурсивно с помощью собственных функций темизации. Это свойство редко используют вместе с #theme. |
#cache | Обозначает массив как кэшируемый и определяет срок его хранения. Если рендерный массив уже был отрендерен, он больше не будет рендироваться, пока не закончится срок хранения кэша. При кэшировании используются стандартные функции Друпала cache_get() и cache_set().
Этот атрибут может содержать такой массив массив:
Обратите внимание, что элементы, помеченные с атрибутом #cache будут хранить кэш до тех пор, пока не запустится крон, не смотря на его срок годности. |
- Spleshka
- 27.01.2012
- 28927
Комментарии
Спасибо!)) Очень полезно!
Спасибо за статью! После 3-х дней мытарств с Друпал 7, понял что вся проблема в том, что я не понимаю этих массивов для рендеринга.
Замечательная статья (и блог) — всё внятно, по сути и наконец-то становится ясен механизм темизации.
Спасибо!
преобразование рендер массивов в HTML код. - это называется визуализация
Хорошая статья! Только в начале возникает пара неясностей с терминами:
"Рендерный массив - это ассоциативный массив ..."
"Рендер массив – классический структурированный массив ..."
1. "Рендерный массив" и "рендер массив" - одно и тоже или разные вещи?
2. Чем отличаются друг от друга ассоциативный массив и классический структурированный массив?
Комментировать