Привет, хабр!
В Друпале как правило все данные хранятся в нодах, термах и сущностях другого типа (например commerce product). Да, есть ещё переменные, в которых хранятся настройки.
В нодах хранить данные удобно: есть куча модулей, хуки, настройки, права и т.п. И есть очень большой соблазн любые данные складывать в ноды/термы. Проблема лишь в том, что для каждого поля в ноде создаётся аж 2 таблицы (field_data_field_*, field_revision_field_*)! И при большом объёме данных удар по производительности очевиден.
Выход есть: в Drupal CMS есть очень удобное и простое API для создания своих таблиц, а модуль Views позаботился о том, чтобы этими данными можно было очень легко играться.
Под катом — руководство, как сделать свою таблицу на Друпал и интегрировать её с Views.
Чтобы интереснее было читать — создадим с нуля тестовый «портал» для скачивания торрентов.
Итак, ставим чистый Drupal 7.23, ставим на него модули Ctools, Views.
Создаём ноду типа Film с полями: field_film_image (постер), field_film_description (описание), создаём пару фильмов для теста.
Торренты будем хранить в кастомной таблице, ссылаясь на нужную ноду фильма.
Создаём тестовый модуль (назову его torrents).
В torrents.install прописываем hook_schema, где описываем нашу таблицу:
После включения модуля — таблица создаётся.
После отключения модуля и удаления — таблица удаляется.
В модуле torrents.module указываем, какой views api мы используем:
Создаём в папке с модулем файл torrents.views.inc, который собственно и содержит информацию о том, как вьюхам понимать данные в нашей таблице:
Дописываем в torrents.module плюшку в виде блока с формой, чтобы добавлять торренты в таблицу.
Привожу код всего модуля:
Далее просто включаем модуль и начинаем создавать вьюшку.
Если сделали всё правильно — у нас при создании вьюхи будет новый доступный тип для выбора: Torrents.
В полях можно будет добавить id торрента, название, ссылку.
В отношениях добавить nid фильма и потом использовать данные ноды.
Также есть фильтры по нашим полям, что конечно же удобно (хотя кое-чего не хватает).
Посмотреть демо и добавить торрентов можно здесь.
В Друпале как правило все данные хранятся в нодах, термах и сущностях другого типа (например commerce product). Да, есть ещё переменные, в которых хранятся настройки.
В нодах хранить данные удобно: есть куча модулей, хуки, настройки, права и т.п. И есть очень большой соблазн любые данные складывать в ноды/термы. Проблема лишь в том, что для каждого поля в ноде создаётся аж 2 таблицы (field_data_field_*, field_revision_field_*)! И при большом объёме данных удар по производительности очевиден.
Выход есть: в Drupal CMS есть очень удобное и простое API для создания своих таблиц, а модуль Views позаботился о том, чтобы этими данными можно было очень легко играться.
Под катом — руководство, как сделать свою таблицу на Друпал и интегрировать её с Views.
Чтобы интереснее было читать — создадим с нуля тестовый «портал» для скачивания торрентов.
Создание своей таблицы
Итак, ставим чистый Drupal 7.23, ставим на него модули Ctools, Views.
Создаём ноду типа Film с полями: field_film_image (постер), field_film_description (описание), создаём пару фильмов для теста.
Торренты будем хранить в кастомной таблице, ссылаясь на нужную ноду фильма.
Создаём тестовый модуль (назову его torrents).
В torrents.install прописываем hook_schema, где описываем нашу таблицу:
torrents.install
/*
* hook_schema implementation
*/
function torrents_schema() {
$schema['torrents'] = array(
'fields' => array(
// id торрента
'id' => array(
'description' => t('Torrent identifier'),
'type' => 'serial',
'unsigned' => TRUE,
'not null' => TRUE,
),
// название торрента
'title' => array(
'description' => t('Torrent title'),
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => '',
),
// nid фильма, к которому привязан торрент
'nid' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => FALSE,
'default' => 0,
'description' => t('Film nid'),
),
// ссылка на торрент
'link' => array(
'description' => t('Torrent link to download'),
'type' => 'varchar',
'length' => 255,
'not null' => FALSE,
'default' => '',
),
// когда торрент добавлен
'created' => array(
'description' => t('Torrent added'),
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
),
'primary key' => array('id'),
);
return $schema;
}
После включения модуля — таблица создаётся.
После отключения модуля и удаления — таблица удаляется.
Дружим нашу таблицу с views
В модуле torrents.module указываем, какой views api мы используем:
/**
* Implements hook_views_api().
*/
function torrents_views_api() {
return array(
'api' => 3,
'path' => drupal_get_path('module', 'torrents'),
);
}
Создаём в папке с модулем файл torrents.views.inc, который собственно и содержит информацию о том, как вьюхам понимать данные в нашей таблице:
torrents.views.inc
/**
* Implements hook_views_data()
*/
function torrents_views_data() {
// объявляем новый тип вьюх - торренты
$data['torrents']['table']['group'] = t('Torrents');
$data['torrents']['table']['base'] = array(
'field' => 'id',
'title' => t('Torrents'),
'help' => t('Torrents table contains torrents info and can be related to nodes'),
);
// мы ссылаемся на ноды, поэтому сообщаем для отношений
// что нам надо прилепить в случае их использования
$data['torrents']['table']['join'] = array(
'node' => array(
'left_field' => 'nid',
'field' => 'nid',
),
);
$data['torrents']['nid'] = array(
'title' => t('Film nid'),
'relationship' => array(
'base' => 'node',
'base field' => 'nid',
'handler' => 'views_handler_relationship',
'label' => t('Related film for torrent'),
'title' => t('Film nid'),
),
);
// далее мы для каждого поля определяем, какой хендлер в каких случаях использовать во вьюхах
$data['torrents']['id'] = array(
'title' => t('Torrent ID'),
'field' => array(
'handler' => 'views_handler_field',
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort',
),
'filter' => array(
'handler' => 'views_handler_filter_numeric',
),
'argument' => array(
'handler' => 'views_handler_argument_numeric',
),
);
$data['torrents']['created'] = array(
'title' => t('Created timestamp'),
'field' => array(
'handler' => 'views_handler_field_date',
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort',
),
'filter' => array(
'handler' => 'views_handler_filter_date',
),
'argument' => array(
'handler' => 'views_handler_argument_date',
),
);
$data['torrents']['title'] = array(
'title' => t('Title'),
'help' => t('Just a title'),
'field' => array(
'handler' => 'views_handler_field',
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort',
),
'filter' => array(
'handler' => 'views_handler_filter_string',
),
'argument' => array(
'handler' => 'views_handler_argument_string',
),
);
$data['torrents']['link'] = array(
'title' => t('Download link'),
'help' => t('Download link'),
'field' => array(
'handler' => 'views_handler_field',
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort',
),
'filter' => array(
'handler' => 'views_handler_filter_string',
),
'argument' => array(
'handler' => 'views_handler_argument_string',
),
);
return $data;
}
Дописываем в torrents.module плюшку в виде блока с формой, чтобы добавлять торренты в таблицу.
Привожу код всего модуля:
torrents.module
/*
* Form to submit torrents
*/
function torrents_add_form($form, &$form_state) {
$form['title'] = array(
'#type' => 'textfield',
'#attributes' => array('placeholder' => 'Название'),
'#required' => TRUE,
);
$form['link'] = array(
'#type' => 'textfield',
'#attributes' => array('placeholder' => 'Ссылка на торрент'),
'#required' => TRUE,
);
$films = db_select('node', 'n')
->fields('n', array('nid', 'title'))
->condition('n.type', 'film')
->execute()
->fetchAllAssoc('nid');
$options = array();
foreach ($films as $value) {
$options[$value->nid] = $value->title;
}
$form['film'] = array(
'#type' => 'select',
'#attributes' => array('placeholder' => 'Фильм'),
'#options' => $options,
'#required' => TRUE,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => 'Добавить торрент',
);
return $form;
}
/*
* Submit torrents form callback
*/
function torrents_add_form_submit($form, &$form_state) {
$id = db_insert('torrents')
->fields(array(
'nid' => $form_state['values']['film'],
'title' => filter_xss($form_state['values']['title']),
'link' => filter_xss($form_state['values']['link']),
'created' => time(),
))->execute();
}
/*
* Implements hook_block_info()
*/
function torrents_block_info() {
$blocks['add_torrent'] = array(
'info' => t('Add torrent'),
'cache' => DRUPAL_NO_CACHE,
);
return $blocks;
}
/*
* Implements hook_block_view()
*/
function torrents_block_view($delta = '') {
$block = array();
switch ($delta) {
case 'add_torrent':
$block['content'] = drupal_get_form('torrents_add_form');
break;
default:
break;
}
return $block;
}
/**
* Implements hook_views_api()
*/
function torrents_views_api() {
return array(
'api' => 3,
'path' => drupal_get_path('module', 'torrents'),
);
}
Созадём views
Далее просто включаем модуль и начинаем создавать вьюшку.
Если сделали всё правильно — у нас при создании вьюхи будет новый доступный тип для выбора: Torrents.
В полях можно будет добавить id торрента, название, ссылку.
В отношениях добавить nid фильма и потом использовать данные ноды.
Также есть фильтры по нашим полям, что конечно же удобно (хотя кое-чего не хватает).
Скриншоты, как это заработало
Вот они, наши поля:

Добавление отношения:


Вот они, наши поля:

Добавление отношения:

Посмотреть демо и добавить торрентов можно здесь.