В этой статье вы узнаете, как открыть таблицу, созданную вашим модулем Drupal, для Views. Зачем тебе это делать? Представления — это мощный модуль для запроса и отображения информации, который может сэкономить массу хлопот при работе с пользовательскими данными, создаваемыми вашим модулем.
Основное внимание в этом руководстве будет уделено данным, которые не абстрагированы как объекты Drupal, а просто хранятся в таблице. Предоставление пользовательских сущностей для Views — это тема, которую я освещал в другой серии Sitepoint.com, поэтому я рекомендую ознакомиться с ней, если это так, вот список моих статей.
В этом репозитории я настроил модуль expose, который вы можете клонировать, отслеживать и даже расширять, если хотите больше узнать. Основная ветвь содержит чистый модуль, который просто создает таблицу, которую я буду использовать в этой статье для иллюстрации процесса. Ветвь с exposed-table
содержит, коммит за коммит, шаги, которые я прошёл ниже.
Поскольку определение схемы находится в модуле, я не буду повторять его здесь. Я, однако, дам вам короткую команду MySQL, чтобы сгенерировать пару фиктивных записей, с которыми можно поиграть. Надеюсь, эта команда достаточно информативна, чтобы описать и структуру таблицы:
INSERT INTO `exposed` (`id`, `name`, `deadline`, `node_id`) VALUES (1, 'Danny', 1399477939, 1), (2, 'Peter', 1399477957, 2);
Выставление таблицы в Drupal Views
Есть два основных шага, которые мы должны предпринять, чтобы представить нашу exposed
таблицу для Views: ознакомить Views с нашим модулем и его файлами, связанными с Views, и рассказать ему о структуре нашей таблицы. Второй шаг является сложным, где вы можете иметь различные степени настройки.
Но обо всем по порядку , реализация hook_views_api () :
/** * Implements hook_views_api(). */ function expose_views_api() { return array( 'api' => 3, 'path' => drupal_get_path('module', 'expose') . '/includes/views', ); }
Это очень простая реализация, в которой мы сообщаем, какой API Views использует наш модуль и где будут размещаться связанные файлы Views. Реализация hook_views_api()
в файле .module
.
Затем пришло время реализовать hook_views_data () , на этот раз в файле с именем expose.views.inc
расположенном в указанной выше папке ( /includes/views/
):
/** * Implements hook_views_data(). */ function expose_views_data() { $data = array(); $data['exposed']['table']['group'] = t('Exposed'); $data['exposed']['table']['base'] = array( 'title' => t('Exposed'), 'help' => t('Contains records we want exposed to Views.'), ); return $data; }
В этой реализации мы расскажем Views о нашей таблице в большом массиве, который мы возвращаем в конце. Во-первых, нам нужно указать группу, частью которой будет наша таблица. Это будет использоваться для определения, откуда берутся поля таблицы в пользовательском интерфейсе. Далее мы сообщаем Views, что exposed
таблица является базовой таблицей (отсюда и base
индекс). Это означает, что мы можем создать представление, которое использует эту таблицу для запуска — в качестве основного запроса. И, как вы можете видеть, для обеих частей информации exposed
ключ на самом деле является именем таблицы в базе данных.
Это первые два шага, которые уже позволят нам увидеть некоторые изменения в пользовательском интерфейсе. Очистите кеш и добавьте новый вид. Вы заметите, что рядом с Content
, User
и т. Д. Теперь у вас есть Exposed
а также тип данных. Это с того момента, когда мы определили таблицу как базовую. Однако, если вы продолжите и отредактируете View сейчас, вы увидите сломанный обработчик в разделе Fields
и ни один из столбцов таблицы не будет найден в качестве полей. Следует также объявить их в Views.
поля
Теперь, когда Views знает о нашей таблице, давайте расскажем также, как обрабатывать столбцы таблицы для отображения, фильтрации и сортировки. Это можно сделать, указав некоторые метаданные о каждом столбце (например, заголовок и описание) и какой обработчик представлений использовать для этого поля для данной задачи. Давайте посмотрим, как это сделать для первых трех столбцов нашей таблицы: id
, name
, deadline
. Внутри реализации hook_views_data()
вставьте следующее прямо перед hook_views_data()
$data
:
// The ID field $data['exposed']['id'] = array( 'title' => t('ID'), 'help' => t('The record ID.'), 'field' => array( 'handler' => 'views_handler_field_numeric', ), 'sort' => array( 'handler' => 'views_handler_sort', ), 'filter' => array( 'handler' => 'views_handler_filter_numeric', ), ); // The Name field $data['exposed']['name'] = array( 'title' => t('Name'), 'help' => t('The record name.'), 'field' => array( 'handler' => 'views_handler_field', ), 'sort' => array( 'handler' => 'views_handler_sort', ), 'filter' => array( 'handler' => 'views_handler_filter_string', ), ); // The Deadline field $data['exposed']['deadline'] = array( 'title' => t('Deadline'), 'help' => t('The record deadline.'), 'field' => array( 'handler' => 'views_handler_field_date', ), 'sort' => array( 'handler' => 'views_handler_sort_date', ), 'filter' => array( 'handler' => 'views_handler_filter_date', ), );
Вроде бы много, но это не так. Для каждого поля мы создаем новый массив внутри exposed
массива (это наша новая таблица), ключ которого назван в честь столбца таблицы. Затем, после некоторой базовой информации ( title
и help
), мы сообщаем Views, какой обработчик использовать для каждой из этих трех операций: field
, sort
и filter
. Первый предназначен для отображения поля, тогда как последние два говорят сами за себя.
Но что такое обработчик? Обработчик — это класс Views, расположенный в папке handlers модуля Views, который обрабатывает эти операции. И здесь нам нужно указать, какой из этих классов следует использовать. Например, для обычного целочисленного поля мы использовали бы целочисленный обработчик для отображения, обычный для сортировки и снова целочисленный для фильтрации. Для крайнего срока у нас есть обработчики даты. И если по умолчанию, который предлагает Views, недостаточно (что может быть так), вы можете расширить эти классы, изменить логику и использовать вместо этого новые пользовательские обработчики.
Теперь вы можете сохранять, очищать кеш и обновлять ваш вид. Вы должны иметь возможность добавлять поля, фильтры и сортировать их. Между тем, представления знают, как обрабатывать каждое поле в зависимости от типа данных, которые они содержат.
присоединяется
Как вы, наверное, заметили, у нас есть еще один столбец в таблице, который мы еще не рассмотрели: node_id
. Это целое число в базе данных, и я полагаю, что мы можем описать его как таковой. Но было бы не очень полезно создавать списки, которые показывают идентификаторы узлов. Скорее, эти идентификаторы должны использоваться во взаимосвязи (объединение таблиц) и извлекать данные из соответствующих узлов. Чтобы сделать это, нам нужно 2 вещи: сообщить Views, с какими другими таблицами может соединяться наша таблица, и установить соответствующие обработчики для столбца node_id
.
Во-первых, давайте удостоверимся, что Views знает, что exposed
таблица может соединиться с таблицей node
. Внутри реализации hook_views_date()
перед описанием полей вставьте следующее:
$data['exposed']['table']['join'] = array( 'node' => array( 'left_field' => 'nid', 'field' => 'node_id', ), );
Таким образом, мы в основном добавляем новое индексное join
в котором ключи массива ниже представляют таблицы, с которыми он будет соединяться. Поле left_field
— это поле в целевой таблице ( node
), а field
— в текущей ( exposed
) таблице. Это может сбивать с толку, поскольку обычно имена столбцов совпадают.
Далее нам нужно определить поле node_id
же, как мы делали все остальное, но с одним дополнительным битом информации, отношениями (и также аргументом):
// The Node ID field $data['exposed']['node_id'] = array( 'title' => t('Node ID'), 'help' => t('The record node ID.'), 'field' => array( 'handler' => 'views_handler_field_node', ), 'sort' => array( 'handler' => 'views_handler_sort', ), 'filter' => array( 'handler' => 'views_handler_filter_numeric', ), 'relationship' => array( 'base' => 'node', 'field' => 'node_id', 'handler' => 'views_handler_relationship', 'label' => t('Node'), ), 'argument' => array( 'handler' => 'views_handler_argument_node_nid', 'numeric' => TRUE, 'validate type' => 'nid', ), );
Обработчик отображения для этого поля взят из реализации модуля Views от имени основного модуля Node (находится в папке modules/node
). Этот обработчик также используется представлениями при отображении идентификатора узла в представлении на основе таблицы node
.
Обработчики для фильтра и сортировки такие же, как и раньше, поскольку мы имеем дело с обычным целым числом. Мы можем фильтровать и сортировать по этому вопросу. Однако у нас также есть ключ relationship
, массив, через который мы указываем таблицу соединений, поле и обработчик. views_handler_relationship
— это класс, который позаботится об отношениях не только для отображения полей из объединенных таблиц, но и для возможности фильтрации и сортировки по ним.
И, наконец, для хорошей меры, я также включил ключ argument
помощью которого мы заботимся об обработке аргументов (контекстных фильтров) на основе идентификатора узла. Используемый для этого обработчик снова зависит от идентификатора узла, именно так, как его реализует модуль Views. Для других полей у вас есть несколько общих обработчиков аргументов, которые вы также можете использовать.
Так что очистите кеш и обновите представление. Теперь вы сможете добавить связь на основе идентификатора узла. Затем вы получите множество новых полей, связанных с узлами, которые вы можете добавлять, фильтровать и сортировать. Кроме того, теперь вы можете добавить контекстный фильтр для этого поля и динамически фильтровать представление на основе идентификатора, переданного в контексте.
Вывод
Как вы можете видеть, работа с Views проста как для разработчика сайта, так и для разработчика. Через несколько простых шагов нам удалось представить данные в нашей собственной пользовательской таблице для Views. Теперь мы можем использовать его для отображения, фильтрации и сортировки наших данных, а также для доступа к связанным сущностям Drupal. Это действительно очень подключаемая система, и если вы недовольны тем, что могут сделать для вас существующие обработчики, не стесняйтесь расширять те, которые подходят ближе, и корректировать их для ваших данных, а затем ссылаться на новые классы в соответствующем определении поля. Удачи!