Взгляд на Views API

Готов перевод третьей статьи из цикла "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 - в них мы исследуем основные инструменты расширения функций Друпала.

Комментарии