Field API

Опубликовано 2012.04.14

Данное API позволит работать с полями. Оно позволяет создавать новые типы полей. В большинстве случаев встроенных типов полей вполне хватает для пользовательских нужд, но при необходимости можно легко добавить свои.

Работу с Field API будем осуществлять в новом модуле. Назовём его test_fields. Используем ещё одну возможность модулей – зависимость одного модуля от другого. Например, для работы одного модуля необходим другой модуль. Сделаем наш второй модуль зависимым от первого. Для этого добавим в info файл строку с dependencies.

  1. name = Модуль для работы с полями.
  2. description = В этом модуле я буду использовать Field API.
  3. package = test_modules
  4. core=7.x
  5. version = "7.x-1.x-dev"
  6. project = "test_fields"
  7. datestamp = "1332419400"
  8. dependencies[] = test_module

Проверяем модуль в списке модулей.

Как видите – модуль для работы с полями зависит от тестового модуля. Оба модуля находятся в одном пакете и сгруппированы.

Давайте создадим поле, которое позволит выбрать пол автора ноды. То есть при создании ноды будет переключатель М/Ж.

Создавать модуль вы уже умеете. Добавим к модулю ещё один файл – install. Этот файл запустится только при первой установке модуля. Его имя также должно совпадать с именем модуля и иметь расширение install. Добавим в него следующую функцию.

Имя файла test_fields.install

  1. function test_fields_field_schema($field) {
  2. return array(
  3. 'columns' => array(
  4. 'textf' => array(
  5. 'type' => 'int',
  6. ),
  7. ),
  8. );
  9. }

Данный код вызовет hook_field_schema, который зарезервирует место в БД для поля с именем textf. К этому имени мы будем обращаться в следующих функциях. Это поле будет типа integer.

Новое поле должно отображаться в конфигурировании полей ноды.

В добавлении нового поля должно появиться наше новое поле. Вначале определим тип поля. Поместим в файл test_fuields.module следующую функцию.

  1. function test_fields_field_info() {
  2. return array(
  3. 'textf' => array(
  4. 'label' => t('Выбор пола'),
  5. 'description' => t('Описание поля'),
  6. 'default_widget' => 'textf_widget',
  7. 'default_formatter' => 'textf_formatter',
  8. ),
  9. );
  10. }

Теперь можно будет добавить к материалу поле типа «Выбор пола».  Значение элемента default_widget , равное textf_widget говорит о том, что тип виджета будет называться textf. С ним мы будем работать чуть позже. Этот виджет будет отвечать за то, какого типа будет поле в форме добавления ноды.

Теперь нужно дать описание полю, чтобы пользователь понимал поле какого типа он добавляет к материалу – поле ввода, текстовую область, выпадающий список и т.д. Можно вписать сюда всё что угодно.

  1. function test_fields_field_widget_info() {
  2. return array(
  3. 'textf' => array(
  4. 'label' => t('Переключатель'),
  5. 'field types' => array('textf'),
  6. ),
  7. );
  8. }

Назовём наше поле переключателем и в поле field types укажем наше имя - textf, с которого мы начинали написание модуля.

Теперь доступно новое поле для ноды.

Также для поля нужен формат вывода.

Для этого используем hook_field_formatter_info. Пусть Drupal будет выводить М/Ж или  Мужчина/Женщина. Напишем следующую функцию.

  1. function test_fields_field_formatter_info() {
  2. return array(
  3. 'textf_formatter' => array(
  4. 'label' => t('Кратко'),
  5. 'field types' => array('textf'),
  6. ),
  7. 'textf_formatter_2' => array(
  8. 'label' => t('Полно'),
  9. 'field types' => array('textf'),
  10. ),
  11. );
  12. }

textf_formatter – это наш дефолтный формат ввода, который мы указали в функции test_fields_field_info.

Теперь в настройках отображения полей мы можем выбрать, как будет выводиться значение поля.

Далее определимся – как будет выглядеть элемент формы на странице добавления ноды. Пусть это будет два радиобутона. Для этого используем hook_field_widget_form и вспомним о создании форм в Drupal. Напишем следующую функцию.

  1. function test_fields_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
  2. switch ($instance['widget']['type']) {
  3. case 'textf':
  4. $element['textf'] = array(
  5. '#type' => 'radios',
  6. '#options' => array(1 => t('М'), 2 => t('Ж')),
  7. '#title' => $element['#title'],
  8. '#description' => $element['#description'],
  9. '#default_value' => isset($items[0]['textf']) ? $items[0]['textf'] : 1,
  10. '#required' => $element['#required'],
  11. '#weight' => isset($element['#weight']) ? $element['#weight'] : 0,
  12. '#delta' => $delta,
  13. );
  14. break;
  15. }
  16. return $element;
  17. }

Далее создадим два формата вывода – полный и краткий, о которых мы говорили ранее. Используем hook_field_formatter_view.

  1. function test_fields_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
  2. $element = array();
  3. switch ($display['type']) {
  4. case 'textf_formatter':
  5. foreach ($items as $delta => $item) {
  6. if ($item['textf']) {
  7. $val = $item['textf'];
  8. if($val==1){
  9. $element[$delta]['#markup'] = 'М';
  10. }elseif($val==2){
  11. $element[$delta]['#markup'] = 'Ж';
  12. }
  13. }
  14. }
  15. break;
  16. case 'textf_formatter_2':
  17. foreach ($items as $delta => $item) {
  18. if ($item['textf']) {
  19. $val = $item['textf'];
  20. if($val==1){
  21. $element[$delta]['#markup'] = 'Мужчина';
  22. }elseif($val==2){
  23. $element[$delta]['#markup'] = 'Женщина';
  24. }
  25. }
  26. }
  27. break;
  28. }
  29. return $element;
  30. }

Теперь можно проверить, как это всё работает, открыв ноду.

И завершающий шаг – это вариант, когда поле не заполнено. Для этого нужно использовать hook_field_is_empty, который вернёт true.

  1. function test_fields_field_is_empty($item, $field) {
  2. if (empty($item['textf'])) {
  3. return true;
  4. }
  5. }

Этого вполне достаточно для создания собственных полей. Вы можете поэкспериментировать, создавая более сложные поля. Чтение документации позволит вам легко расширить/модифицировать данный код.