Готов перевод третьей статьи из цикла "20 API за 20 дней". В ней рассказывается о том, как встроить данные своего модуля во Views, рассматриваются некоторые хуки Views API. Статья не очень большая, всех секретов мироздания не раскрывает. Но базовая информация о предмете приведена, плюс указаны направления для дальнейшего изучения.
Оригинальная статья: View on Views API.
Автор: Мартин Грабовцин.
Переводили: graker, pereskokov.
Взгляд на Views API
Среди дополнительных модулей Друпала Views - самый широко используемый. Он предлагает возможность легко создавать страницы и блоки динамического содержимого, которые можно разрабатывать прямо через веб-интерфейс. Также он позволяет администраторам сайта прикреплять к представлениям фильтры, обеспечивающие для пользователя возможность без особых усилий прореживать данные.
А еще модуль Views обладает определенным API для программной работы с представлениями. Разработчики могут вызывать представления внутри модулей, модифицировать отображение представлений и даже программно создавать новые представления. Существует исчерпывающая документация и раздел для обсуждения в сообществе Друпала, посвященные различным способам прогрммной работы с представлениями. В данном выпуске цикла "20 API за 20 дней" мы рассмотрим несколько не очень известных возможностей API, которые наша команда находит полезными в разработке сайтов.
Хуки данных модуля Views
Если вы разрабатываете модули, то скорее всего неоднократно хотели, чтобы при установке вашего модуля в нем уже были какие-то представления Views. Также, возможно, вам хотелось, чтобы данные, генерируемые модулем, можно было отображать и в пользовательских представлениях. Views API предоставляет нам хуки данных, позволяющие этого добиться.
Хуки данных созданы для разработчиков, желающих интегрировать свои модули в модуль Views. На базовом уровне хуки данных позволяют разработчикам рассказать модулю Views, как включать сгенерированные их модулями данные в представление. Также они предоставляют модулю Views некоторую информацию об этих данных и о том, как они связаны с остальным содержимым сайта. На более продвинутом уровне хуки данных позволяют управлять способами отображения информации во Views, а также такими сложными операциями, как фильтрация и сортировка. В целом, этот набор хуков обеспечивает разработчиков полным спектром способов привязки функций своих модулей к модулю Views.
Хуки данных, доступные разработчикам в модуле Views 6.x:
- hook_views_api - этот очень простой хук регистрирует модуль во Views API. Он возвращает некоторые данные о поддерживаемой модулем версии Views API.
- hook_views_default_views - этот хук позволяет разработчикам модулей создавать собственные представления при инсталляции модулей. Это избавляет пользователей от необходимости самостоятельно создавать представления, а также обеспечивает наличие добротных интерфейсов в модуле.
- hook_views_data - данный хук передает модулю Views информацию о таблицах, из которых Views может извлечь данные. Он определяет отношения между этими и другими таблицами в Друпале, чтобы модуль Views мог составить подходящие запросы.
- hook_views_handlers - этот хук делает две простые вещи: во-первых, позволяет разработчикам контролировать, как будет отображаться при создании представления интерфейс каждого поля. Во-вторых, он управляет отображением поля в самом представлении. Но у него есть и более сложные функции.
- hook_views_plugins - модуль Views можно расширять новыми плагинами. Плагины могут вводить во Views новые способы вывода представлений (отображения, стили, строки), контроля за доступом к представлениям и валидации аргументов.
Вместе эти функции, входящие в набор хуков данных, создают мощный API для связи с представлениями Views. С их помощью ваш модуль может передавать в представления Views данные, управлять способом их отображения и реализовывать сложную фильтрацию. Вот пример хуков данных в действии, взятый из модуля nodequeue:
/**
* hook_views_api - регистрирует модуль во Views API
* В данном примере Друпалу сообщается, что необходимо использовать API версии 2
*/
function nodequeue_views_api() {
return array(
'api' => 2,
'path' => drupal_get_path('module', 'nodequeue') .'/includes/views',
);
}
/**
* Реализация hook_views_data()
*
* hook_views_data рассказывает модулю Views, где искать данные. Для каждого нового поля представления
* здесь должна быть запись. В рамках примера функция сокращена ради экономии места.
*
*/
function nodequeue_views_data() {
$data = array();
// ----------------------------------------------------------------
// Таблица nodequeue_nodes
$data['nodequeue_nodes']['table']['group'] = t('Nodequeue');
// В данном примере показано, как поле связывается с представлениями. Фильтрующая и сортирующая
// функции привязываются к полю, что позволяет представлениям выполнять эти функции без необходимости
// писать дополнительный код.
$data['nodequeue_nodes']['position'] = array(
'title' => t('Position'),
'help' => t('The position of the node within a queue.'),
'field' => array(
'handler' => 'views_handler_field_numeric',
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort',
),
'filter' => array(
'handler' => 'views_handler_filter_numeric',
),
'argument' => array(
'handler' => 'views_handler_argument_numeric',
),
);
// обратите внимание, какие хэндлеры сортировки и фильтрации применяются к полям.
// В модуле Views есть собственные инструменты для работы с датами, числами, текстом и другими видами данных.
$data['nodequeue_nodes']['timestamp'] = array(
'title' => t('Added date'),
'help' => t('The date the node was added to a queue.'),
'field' => array(
'handler' => 'views_handler_field_date',
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort_date',
),
'filter' => array(
'handler' => 'views_handler_filter_date',
),
);
// в этой части функции содержится группа других полей, но предыдущих двух
// достаточно для примера привязки полей к представлениям
//...
return $data;
}
/**
* Реализация hook_views_handlers()
*
* hook_views_handlers рассказывает модулю Views, как показывать поля в интерфейсе Views и
* как их отображеть в самом представлении. В директории модуля вы найдете файл, соответствующий каждому
* parent-элементу массивов.
*
*/
function nodequeue_views_handlers() {
return array(
'info' => array(
'path' => drupal_get_path('module', 'nodequeue') .'/includes/views',
),
'handlers' => array(
'nodequeue_handler_argument_subqueue_qid' => array(
'parent' => 'views_handler_filter_numeric',
),
'nodequeue_handler_field_all_queues' => array(
'parent' => 'views_handler_field_prerender_list',
),
'nodequeue_handler_field_all_subqueues' => array(
'parent' => 'nodequeue_handler_field_all_queues',
),
'nodequeue_handler_field_links' => array(
'parent' => 'views_handler_field_node_link',
),
'nodequeue_handler_field_queue_tab' => array(
'parent' => 'views_handler_field_node_link',
),
'nodequeue_handler_filter_in_queue' => array(
'parent' => 'views_handler_filter_boolean_operator',
),
'nodequeue_handler_relationship_nodequeue' => array(
'parent' => 'views_handler_relationship',
),
),
);
}
Это достаточно простой пример работы с хуками данных в собственных модулях для их привязки к Views API. Ни в коем случае не считайте его исчерпывающим. Подробная документация по Views API доступна по адресу http://views.doc.logrus.com/.
Изменяйте представления при построении
Еще одна группа хуков Views API - изменяющие хуки. С помощью этих хуков вы можете менять поведение представления Views на разных фазах его построения. Изменения могут быть любыми, какие только возможны через интерфейс Views. Каждое представление - это объект PHP, состоящий из множества разных свойств. Изменение этих свойств может изменить и результирующее представление. Давайте посмотрим на список изменяющих хуков, приведенных в порядке их вызова модулем Views:
- hook_views_pre_view - данный хук вызывается в самом начале обработки представления, прежде всего остального.
- hook_views_pre_execute - хук вызывается прямо перед запуском процесса. Запрос уже полностью сформирован, но еще не обработан функцией db_rewrite_sql.
- hook_views_pre_render - этот хук вызывается перед процессом генерации представления. Запрос уже был выполнен, фаза pre_render() для хендлеров уже прошла, так что все данные должны быть доступны.
- hook_views_post_render - пост-обработка данных в сгенерированном представлении.
У изменяющих хуков много применений в разработке, они могут сделать представления более удобными без необходимости писать много кода. Данный пример демонстрирует, как прикрепить какой-нибудь текст перед представлением. Использование hook_views_pre_render позволяет нам убрать PHP-код из заголовка представления и отображать некоторые представления в более постоянной форме:
Помимо управления отображением представлений, можно также модифицировать их фильтры и сортировки. Данный пример демонстрирует, как изменить порядок, в котором представление выводит данные.
function MYMODULE_views_pre_render(&$view) {
if ($view->name == 'view-i-want-to-change') {
// мы задали 3 сортировки в интерфейсе создания представления
$available_sorts = array('node_title' => t('Title'), 'node_created' => t('Post Date'), 'user_name' => t('Author'));
// определяем, какая сортировка доступна
$current_sort = isset($_GET['sort']) && isset($available_sorts[$_GET['sort']) ? $_GET['sort'] : 'node_title';
// теперь мы удалим все сортировки кроме используемой
$sort = $view->display_handler->get_option('sort');
foreach (array_keys($sort) as $sort_name) {
if ($sort_name != $current_sort) {
// вот мы удаляем неиспользуемые сортировки
unset($sort[$sort_name]);
}
}
$view->display_handler->sort_option('sort', $sort);
// формируем ссылки для сортировок
$links = array();
foreach ($available_sorts as $type => $title) {
$links[] = array(
'title' => $title,
'path' => $_GET['q'],
'query' => array('sort' => $type)
);
}
// прикрепляем ссылки к представлению
$view->attachment_before = theme('links', $links);
}
}
/**
* Прикрепляем описание термина к представлению с аргументом
*/
function MYMODULE_views_pre_render(&$view) {
if ($view->name == 'view-i-want-to-change') {
// у нас есть доступ к аргументам views
$term = taxonomy_get_term($view->args[0]);
if ($term) {
$view->attachment_before = check_markup($term->description, FILTER_FORMAT_DEFAULT, FALSE);
}
}
}
Следует отметить, что правильное изменение сортировки представления может причинить немало головной боли и потребовать решить кучу проблем. Для исследования объектов представлений не забывайте использовать модуль Devel и его прекрасную функцию dpm, они избавят вас от необходимости целыми днями чесать репу. Вот пример:function MYMODULE_views_pre_render(&$view) {
dpm($view);
}
Приводите код в порядок
В данной статье упоминалось много хуков; в целом нет никакой необходимости хранить весь код Views API в одном файле. По правде говоря, как правило, это плохая мысль - хранить все в одном месте - так как загрузка всего кода при каждой загрузке представления приведет к проблемам производительности. Но во Views API код может быть разделен на несколько файлов без особых трудностей; тогда для генерации представления будут загружаться только необходимые файлы.
Так какой хук куда класть? Некоторые размышления привели к общим принципам структурирования кода в модулях так, чтобы с ними было легче работать. Ниже набросана небольшая схема для демонстрации обычного шаблона реализации кода Views.
- MYMODULE.module – основной файл модуля
- hook_views_api
- Все изменяющие хуки (hook_views_pre_view, hook_views_pre_execute, hook_views_pre_render, hook_views_post_render)
- MYMODULE.views.inc – в данном файле содержатся хуки, которые передают данные и плагины представлениям
- hook_views_data
- hook_views_handlers
- hook_views_plugins
- MYMODULE.views_default.inc – содержит только один хук с длинными определениями представлений
- hook_views_default_views
Другие важные функции, которые должен знать каждый разработчик
Наконец, Views API состоит не только из хуков, но и из небольших функций, облегчающих жизнь разработчику. Если вы планируете усиленно ковыряться во Views, стоит потратить время на тщательное исследование документации с целью лучшего понимания всего, что может предложить модуль Views. Вот некоторые из самых полезных функций, о которых должен знать каждый разработчик:
- views_embed_view - используйте эту функцию, чтобы отобразить представление на web-странице. Очень просто.
- views_get_view - функция возвращает весь гигантский объект представления целиком. Используйте ее, когда хотите изменить основные параметры, связанные с представлением, без необходимости лезть в изменяющие хуки. Есть определенные вещи, которые нельзя модифицировать через изменяющие хуки, поэтому иногда эта функция представляется более кратким путем к цели.
Дополнительные ресурсы
Данный обзор описывает лишь некоторые подходы к работе с представлениями - те, которыми мы часто пользуемся в компании Trellon. Ниже приводится список дополнительных ресурсов для подробного изучения Views API и изыскания своих собственных решений типовых задач. Убедитесь, что прочли все наши статьи про API - в них мы исследуем основные инструменты расширения функций Друпала.