Добро пожаловать ко второй части этого урока, в которой мы исследуем мир пользовательских объектов в Drupal. Если вы этого еще не сделали, я настоятельно рекомендую вам прочитать первую часть, но, тем не менее, давайте сделаем краткое резюме.
В предыдущей статье мы определили схему для нашего типа сущности и зарегистрировали ее в Drupal. Мы также переопределили EntityAPIController
В этой части урока мы продолжим и поговорим о нескольких других интересных вещах, которые мы можем сделать с сущностями в Drupal. Сначала мы быстро настроим страницы, на которых мы можем отображать отдельные объекты проекта. Далее мы создадим простой, но очень мощный интерфейс администратора для управления ими. Затем мы сделаем наш тип сущности полевым, чтобы мы могли добавлять поля через пользовательский интерфейс. И, наконец, мы представим его представлениям, чтобы мы могли создавать правильные списки объектов проекта.
Если вы хотите, вы можете следовать исходному коду из первой ветви репозитория Git или заглянуть во вторую ветку, которая содержит весь код, который мы рассмотрим сегодня.
Страницы отдельных лиц
Первое, что мы сделаем, это создадим страницы для отображения отдельных объектов проекта. Мы начнем с добавления нового элемента в нашу реализацию hook_menu()
$items['project/%'] = array(
'title' => 'Project',
'page callback' => 'demo_view_project',
'page arguments' => array(1),
'access arguments' => array('access content'),
);
Мы регистрируем путь ( project/id
demo_view_project()
Что касается доступа, любой, кто имеет access content
Далее, давайте напишем упомянутую функцию обратного вызова (имейте в виду, что это простой пример только для демонстрации):
/**
* Callback function for displaying the individual project page
*/
function demo_view_project($id) {
$projects = entity_load('project', array($id));
$project = $projects[$id];
drupal_set_title($project->name);
$output = entity_view('project', array($project));
return $output;
}
Это опять-таки очень просто: мы загружаем сущность с идентификатором, переданным из URL, мы устанавливаем заголовок страницы, запускаем объект сущности через entity_view()
Мы рассматривали эти концепции Entity API в последний раз, когда перечисляли наши проекты. Теперь вы можете очистить кеш и перейти к project/1
Пользовательский интерфейс администратора
Теперь, когда мы можем отображать отдельные объекты, давайте использовать возможности модуля Entity API для настройки быстрого интерфейса администратора для управления ими. Для этого нужно сделать несколько простых шагов.
Во-первых, давайте отредактируем нашу реализацию hook_entity_info()
...
'access callback' => 'demo_access_callback',
'uri callback' => 'entity_class_uri',
'admin ui' => array(
'path' => 'admin/projects',
'controller class' => 'EntityDefaultUIController',
),
...
И замените эту строку:
'entity class' => 'Entity',
С этим:
'entity class' => 'ProjectEntity',
С помощью этих модификаций мы делаем 4 вещи:
- Мы указываем функцию обратного вызова доступа для типа объекта. Нам это понадобится для интерфейса администратора, и мы объявим функцию обратного вызова через минуту.
- Мы устанавливаем
uri callback
- Мы устанавливаем информацию пользовательского интерфейса
admin ui
EntityDefaultUIController
entity.ui.inc
-
Мы изменяем имя класса сущности для этого типа сущности на тот, который еще не существует. Мы создадим его сейчас, расширив предыдущий, чтобы мы могли переопределить его
defaultUri()
/** * Project entity class extending the Entity class */ class ProjectEntity extends Entity { /** * Change the default URI from default/id to project/id */ protected function defaultUri() { return array('path' => 'project/' . $this->identifier()); } }
Как видите, мы в основном меняем этот путь к индивидуальной сущности проекта, возвращаемой этим методом класса. Когда придет время, я укажу, почему это было удобно, но это будет по умолчанию, который я упомянул в пункте 2. Теперь давайте также быстро объявим нашу функцию обратного вызова доступа, упомянутую в пункте 1:
/**
* Access callback for project entities.
*/
function demo_access_callback($op, $project = NULL, $account = NULL) {
if ($op == 'view' || $op == 'update' || $op == 'create' || $op == 'delete') {
return TRUE;
}
else {
return FALSE;
}
}
Как вы можете видеть, это не большая функция обратного вызова доступа, поскольку она возвращает true для всего. Здесь вы обычно выполняете правильные проверки доступа, но для демонстрационных целей он работает просто отлично.
Теперь есть еще одна вещь, которую нам нужно сделать, чтобы использовать наш интерфейс администратора: объявить простую форму добавления / редактирования для объекта проекта и его обработчика отправки:
/**
* Form definition for adding / editing a project.
*/
function project_form($form, &$form_state, $project = NULL) {
$form['name'] = array(
'#title' => t('Project name'),
'#type' => 'textfield',
'#default_value' => isset($project->name) ? $project->name : '',
'#required' => TRUE,
);
$form['description'] = array(
'#title' => t('Project description'),
'#type' => 'textarea',
'#default_value' => isset($project->description) ? $project->description : '',
'#required' => TRUE,
);
$form['deadline'] = array(
'#title' => t('Project deadline'),
'#type' => 'textfield',
'#default_value' => isset($project->deadline) ? $project->deadline : '',
'#required' => TRUE,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => isset($project->id) ? t('Update project') : t('Save project'),
'#weight' => 50,
);
return $form;
}
/**
* Submit handler for the project add/edit form.
*/
function project_form_submit($form, &$form_state) {
$project = entity_ui_form_submit_build_entity($form, $form_state);
$project->save();
drupal_set_message(t('The project: @name has been saved.', array('@name' => $project->name)));
$form_state['redirect'] = 'admin/projects';
}
Для поля deadline
Обычно вы хотите использовать модуль Date для создания красивого виджета, а затем сохранить это значение как метку времени. Но это подойдет для нашего примера.
В остальном ничего особенного не происходит. Несколько вещей, которые вы должны иметь в виду, хотя. Для того чтобы Entity API автоматически распознал тот факт, что это форма для сущностей проекта, объявленное имя функции должно быть именно таким. Если бы тип сущности был назван chocolate
chocolate_form()
Вы также заметите, что мы передаем сущность $project
Это будет обработано Entity API для формы редактирования. И, наконец, в обработчике отправки вы заметили использование функции entity_ui_form_submit_build_entity () . Это отличный помощник, который возьмет все значения из массива $form_state
Вот и все. Мы можем очистить кеш и перейти по http://example.com/admin/projects
Ранее я упоминал, что сообщу вам, почему мы должны переопределить класс Entity
Ссылка Drupal, размещенная за названиями проектов, генерируется на основе этой информации. Поэтому, пока путь существует, у вас должна быть полноценная система CRUD + страницы для отображения отдельных объектов. Неплохо.
поля
Следующее, что мы увидим, — как сделать наши объекты доступными для полей. Давайте снова отредактируем реализацию hook_entity_info()
...
'fieldable' => TRUE,
'bundles' => array(
'project' => array(
'label' => t('Project'),
'admin' => array(
'path' => 'admin/projects',
),
),
),
...
В первой строке мы сообщаем Drupal, что этот тип сущности должен использовать поля, а в следующих строках мы определяем пакет, к которому они могут быть присоединены. Пакеты — это то, к чему мы присоединяем поля в Drupal, и любой тип сущности может иметь несколько пакетов. Например, в новой установке Drupal у сущности узла есть статья и пакеты страниц (типы контента).
Мы определяем один, называемый project
Теперь, если вы очистите кеш и зайдите в admin/projects
Теперь мы можем добавить поля к нашей сущности.
Вы также заметите, что после добавления некоторых полей через пользовательский интерфейс и попытки редактирования или добавления проекта вы не видите поля в форме. Это потому, что мы должны включить их. Отредактируйте функцию project_form()
field_attach_form('project', $project, $form, $form_state);
Используя Field API field_attach_form () , мы присоединяем к форме все необходимые элементы, объявленные через пользовательский интерфейс. Теперь перейдите к форме еще раз, и вы должны увидеть новые поля. И даже на отдельной странице отображения сущности проекта значения полей отображаются при настройке через пользовательский интерфейс.
Предоставление типа объекта представлениям
Последнее, что мы собираемся рассмотреть, — это показать объектам нашего проекта представления. Самое основное, что мы можем сделать в этом отношении, это отредактировать реализацию hook_entity_info()
...
'views controller class' => 'EntityDefaultViewsController',
...
Теперь вы можете просто очистить кеш и создать новый вид. Убедитесь, что вы выбрали Project
Content
Следует отметить, что Views не может интерпретировать типы значений, которые мы храним в этих свойствах. Например, поле deadline
Поэтому, если вы добавите это поле, оно будет обрабатываться как простое числовое значение.
Чтобы это исправить, нам нужно реализовать hook_entity_property_info()
/**
* Implements hook_entity_property_info().
*/
function demo_entity_property_info() {
$info = array();
$info['project']['properties']['id'] = array(
'label' => t('Project ID'),
'description' => t('The ID of the project.'),
'type' => 'integer',
'schema field' => 'id',
);
$info['project']['properties']['name'] = array(
'label' => t('Project name'),
'description' => t('Name of the project.'),
'type' => 'text',
'schema field' => 'name',
);
$info['project']['properties']['description'] = array(
'label' => t('Project description'),
'description' => t('Description of the project.'),
'type' => 'text',
'schema field' => 'description',
);
$info['project']['properties']['deadline'] = array(
'label' => t('Deadline'),
'description' => t('Project deadline.'),
'type' => 'date',
'schema field' => 'deadline',
);
return $info;
}
Как видите, это ситуация с большим вложенным массивом, в которой для объекта project
Теперь, если вы очистите кеш и добавите эти поля в свой вид, представления будут знать, какие значения хранятся в свойствах. Для поля deadline
Важная вещь, которую следует иметь в виду при реализации этого хука: вы не можете сделать это только для одного свойства. Как только вы внедрили и описали одно из своих свойств, вам необходимо добавить и остальные. В противном случае Views больше не будет отображать все остальное.
Вывод
Мы достигли конца нашего исследования сущностей Drupal. И хотя мы довольно много рассмотрели, есть еще много вещей, которые вы можете сделать, чтобы усовершенствовать и настроить типы ваших сущностей. В этой части мы увидели, как интегрироваться с Views, как добавлять поля в наши сущности и даже как создавать для них интерфейс администратора. Но вы можете сделать больше: режимы просмотра, ревизии и т. Д.
Мы написали пример кода и создали потрясающую функциональность. И да, со строгой точки зрения «мальчик это долго читал», это было довольно интенсивно и сложно. Но если вы сделаете шаг назад и задумаетесь о том, чего мы достигли с тем, что, как я вам гарантирую, почти не содержит кода, вы поймете, почему система сущностей Drupal так хороша.