Наверняка, многие, работающие с друпалом, знакомы с модулем Views. Как гласит Drupaler.ru, модуль Views — это Настройка и контроль за отображением любого типа контента в любом месте сайта, т.е. он позволяет создавать страницы, блоки, подменять содержимое нод, страниц пользователей и многое другое, формируя контент из любых доступных полей на сайте. Но что делать, когда необходимо вывести информацию, предоставляемую сторонним модулем, и к которой доступа из Views у нас нет?
Чтобы было понятно, далее всё на живом примере:
На сайте я использую модуль PrivateMSG. Он позволяет пользователям отправлять друг другу личные сообщения. С помощью Views я собрал блок, в котором отображается информация о текущем пользователе.
Задача: Отобразить в блоке количество новых сообщений и количество всех сообщений в папке «Входящие» текущего пользователя.
Решение: Написать модуль, который добавил бы в конструктор Views необходимые значения.
К сожалению на просторах интернета очень мало информации по этому поводу, а мануал по Views API довольно сложен и непонятен.
Итак, приступим.
После всего проделанного Views сформирует запрос типа
и вернет необходимые значения.
Надеюсь, инструкция окажется полезной для кого-то. Если будет интерес, могу написать более подробно о Views, там еще много интересного: как создать свои настройки для полей, как создавать поля, доступные в фильтрах и сортировках, свои аргументы и связи, и многое другое.
UPD: Перенес в блог «Drupal». Спасибо за карму.
Чтобы было понятно, далее всё на живом примере:
На сайте я использую модуль PrivateMSG. Он позволяет пользователям отправлять друг другу личные сообщения. С помощью Views я собрал блок, в котором отображается информация о текущем пользователе.
Задача: Отобразить в блоке количество новых сообщений и количество всех сообщений в папке «Входящие» текущего пользователя.
Решение: Написать модуль, который добавил бы в конструктор Views необходимые значения.
К сожалению на просторах интернета очень мало информации по этому поводу, а мануал по Views API довольно сложен и непонятен.
Итак, приступим.
- Создаем новый модуль.
Как положено, создаем директорию, называем её именем нашего будущего модуля. Я назвал его privatemsg_extraviews.
В директории создаем файлы privatemsg_extraviews.info, privatemsg_extraviews.module, privatemsg_extraviews.views.inc. Далее нам понадобится создать еще 2 файла, но об этом позже.
- privatemsg_extraviews.info
Этот файл содержит информацию о нашем модуле. Нужен, чтобы друпал опознал модуль.
name = privatemsg_extraviews
description = Добавляет поддержку views в Private Messages
core = 6.x
package = Mail
version = "6.x-1.1"
* This source code was highlighted with Source Code Highlighter.
Этого достаточно, чтобы друпал опознал наш модуль.
- privatemsg_extraviews.module
Основной файл модуля. В нем пишется вся структура модуля, все хуки, и вообще всё-всё.
Нам нужно лишь указать, что модуль работает с Views.
<?php
/**
* Implementation of hook_views_api().
*/
function privatemsg_extraviews_views_api() {
return array(
'api' => 2, // Указываем версию API
'path' => drupal_get_path('module', 'privatemsg_extraviews'), // Указываем откуда брать файл для Views
);
}
* This source code was highlighted with Source Code Highlighter.
- privatemsg_extraviews.views.inc
Самое интересное. В этом файле мы и пишем всю систему работы с Views. Модуль его сам найдет, т.к. мы указали директорию в хуке выше.
Основной хук, который нам потребуется, это hook_views_data(). В нем мы определяем, какую таблицу БД мы добавляем, и какую информацию возвращаем.
<?php
function privatemsg_extraviews_views_data() {
// Определяем новую группу во Views
$data['privatemsg']['table']['group'] = t('Private Messages');
// Указываем таблицы
$data['privatemsg']['table']['join'] = array(
// users - значит наши значения будут доступны только при выборке пользователей
'users' => array(
// Указываем ключи
'left_field' => 'uid',
'field' => 'uid',
),
);
// count - столбец таблицы, по которому будет выборка
$data['privatemsg']['count'] = array(
'title' => t('Количество входящих сообщений'),
'help' => t('Количество сообщений в папке "Входящие"'),
// Указываем возвращаемое поле
'field' => array(
// Обработчик для этого поля
'handler' => 'privatemsg_extraviews_handler_field_count',
// Доступна сортировка по этому полю
'click sortable' => TRUE,
),
);
// Аналогично
$data['privatemsg']['count_new'] = array(
'title' => t('Количество новых сообщений'),
'help' => t('Количество новых сообщений в папке "Входящие"'),
'field' => array(
'handler' => 'privatemsg_extraviews_handler_field_count_new',
'click sortable' => TRUE,
),
);
return $data;
}
* This source code was highlighted with Source Code Highlighter.
Далее нам потребуется hook_views_handlers() для инициализации обработчиков полей.
function privatemsg_extraviews_views_handlers() {
return array(
// Обработчики
'handlers' => array(
'privatemsg_extraviews_handler_field_count' => array(
// Указываем, что возвращаем числовое значение
'parent' => 'views_handler_field_numeric',
// И путь к файлу обработчика
'path' => drupal_get_path('module', 'privatemsg_extraviews'),
),
// Аналогично
'privatemsg_extraviews_handler_field_count_new' => array(
'parent' => 'views_handler_field_numeric',
'path' => drupal_get_path('module', 'privatemsg_extraviews'),
),
),
);
}
* This source code was highlighted with Source Code Highlighter.
Как я уже и говорил выше, нам понадобится создать еще 2 файла — это как раз обработчики полей. Создадим в директории модуля файлы privatemsg_extraviews_handler_field_count.inc и privatemsg_extraviews_handler_field_count_new.inc.
- privatemsg_extraviews_handler_field_count.inc
Обработчик для поля «Количество сообщений».
<?php
// Определяем обработчик, наследуем от стандартного класса "числовое значение"
class privatemsg_extraviews_handler_field_count extends views_handler_field_numeric {
// Запрос к БД
function query() {
// Определяем таблицу
$table = $this->query->ensure_table('pm_index');
// Запрашиваем количество сообщений
$sql = "SELECT COUNT(DISTINCT thread_id) FROM {pm_index} p WHERE p.deleted = 0 AND p.uid = users.uid";
// Указываем название для возвращаемого поля
$this->query->add_field('', "($sql)", 'count');
$this->field_alias = 'count';
}
// Возвращаем полученное значение
function render($values) {
$txt = $values->count;
if ($txt) {
return $txt;
}
else {
return parent::render($values);
}
}
}
* This source code was highlighted with Source Code Highlighter.
- privatemsg_extraviews_handler_field_count_new.inc
Обработчик для поля «Количество новых сообщений». (аналогично)
<?php
class privatemsg_extraviews_handler_field_count_new extends views_handler_field_numeric {
function query() {
$table = $this->query->ensure_table('pm_index');
$sql = "SELECT COUNT(DISTINCT thread_id) FROM {pm_index} p WHERE p.deleted = 0 AND p.is_new = 1 AND p.uid = users.uid";
$this->query->add_field('', "($sql)", 'count_new');
$this->field_alias = 'count_new';
}
function render($values) {
$txt = $values->count_new;
if ($txt) {
return $txt;
}
else {
return parent::render($values);
}
}
}
* This source code was highlighted with Source Code Highlighter.
После всего проделанного Views сформирует запрос типа
SELECT users.uid AS uid,
(SELECT COUNT(DISTINCT thread_id) FROM pm_index p WHERE p.deleted = 0 AND p.uid = users.uid) AS count,
(SELECT COUNT(DISTINCT thread_id) FROM pm_index p WHERE p.deleted = 0 AND p.is_new = 1 AND p.uid = users.uid) AS count_new
FROM users users
WHERE users.uid = 1
* This source code was highlighted with Source Code Highlighter.
и вернет необходимые значения.
Надеюсь, инструкция окажется полезной для кого-то. Если будет интерес, могу написать более подробно о Views, там еще много интересного: как создать свои настройки для полей, как создавать поля, доступные в фильтрах и сортировках, свои аргументы и связи, и многое другое.
UPD: Перенес в блог «Drupal». Спасибо за карму.