Drupal → Пишем вычисляемое поле для Views 2

29.12.2011

Вычисляемое поле (или виртуальное поле, пользовательское поле, computed field, calculated field) — это поле, которого физически нет в таблице, и значение которого вычисляется на основании других полей или подзапроса.

Добавить такое поле в представление Views можно несколькими способами, но drupal way — это написать свой хэндлер (field handler).

Для примера создадим поле, которое будет выводить количество файлов, прикреплённых к материалу с помощью модуля FileField.

1. В основном файле модуля реализуем хук hook_views_api():

/**
 * Implements hook_views_api()
 */
function MODULENAME_views_api() {
  return array('api' => 2);
}

2. В папке модуля создаём файл MODULENAME.views.inc и реализуем в нём хук hook_views_data(), в котором описываем новое поле:

/**
 * Implements hook_views_data()
 */
function MODULENAME_views_data() {
  return array(
    'views' => array(                                                // виртуальная таблица модуля Views
      'files_count' => array(                                        // системное название виртуального поля
        'title' => t('Files count'),                                 // человекопонятное название поля
        'help' => t('Number of attached files'),                     // описание поля
        'group' => t('Content'),                                     // группа, в которой будет поле
        'field'  => array(
          'handler' => 'MODULENAME_views_handler_field_files_count', // хэндлер поля
          'click sortable' => TRUE,                                  // включаем возможность пользовательской сортировки по этому полю
        ),
      ),
    ),
  );
}

3. В этом же файле реализуем хук hook_views_handlers(), в котором указываем базовую информацию о хэндлере:

/**
 * Implements hook_views_handlers()
 */
function MODULENAME_views_handlers() {
  return array(
    'handlers' => array(
      'MODULENAME_views_handler_field_files_count' => array(
        'parent' => 'views_handler_field_numeric',
        'file' => 'MODULENAME_views_handler_field_files_count.inc',
      ),
    ),
  );
}

4. В папке модуля создаём файл MODULENAME_views_handler_field_files_count.inc и реализуем в нём класс хэндлера, унаследованный от views_handler_field_numeric:

class MODULENAME_views_handler_field_files_count extends views_handler_field_numeric {
  function query() {
    $this->field_alias = $this->query->add_field(
      NULL,
      '(SELECT COUNT(*) FROM {content_field_files} cff WHERE cff.nid = node.nid)',
      'files_count'
    );
  }
   
  function click_sort($order) {
    $this->query->add_orderby(NULL, NULL, $order, $this->field_alias);
  }
}

В методе query() добавляется подзапрос, который возвращает количество файлов для каждого материала.

В методе click_sort() добавляется возможность пользовательской сортировки по виртуальному полю (родительский метод не умеет делать сортировку по синониму).

На этом всё. Сбрасываем кэш, создаём представление, добавляем поля, добавляем новое поле Files count (скриншот) и смотрим результат:

Пример field хэндлера для Views 3.

Написанное актуально для
Views 6.x-2.x
Похожие записи

Комментарии

Алекс
29.12.2011, 23:21

В методе click_sort() добавляется возможность пользовательской сортировки по виртуальному полю (родительский метод не умеет делать сортировку по синониму).

а вот об этом не знал, спасибо!
Недавно сделал "интеграцию" с виевс для модуля подписок, и кол-во подписавшихся для каждой категории как раз и было виртуальным полем, и при попытке его сортировать выбивало ошибку, сейчас ошибок нет но и работать не хочет, ведет себя странно при сортировке... Сейчас попробую добавить click_sort().
Кстати я делал не дополнительный запрос внутри запроса, а count(), возможно по-этому и глючит.

а я убил целый день на поиск этого метода) по логике за сортировку таблицы должен отвечать соответствующий sort handler, но это не так

Алекс
30.12.2011, 00:14

у меня с пол дня точно ушло, пользовался только этим. В общем как я понял логика у них какая-то, вот только немного не доделана )
Там еще проблемы с группировкой были, если в хэндлере одного поля указываю группировку, то автоматом и другое поле туда же добавляется, в общем эти вьюхи такие вьюхи =)
Могу скинуть то что получилось с модулем subscriptions, поставленные задачи конечно выполняет, но сделано было на скорую руку... )

Андрей
05.06.2012, 00:42

А реально ли сделать сортировку по виртуальному полю? т.е. может ли она физически работать? или сортировать можно лишь по данным из базы? Скорее всего это возможно, наверное надо свой хендлер писать? может подскажете куда рыть... и где подсматривать...

Андрей
05.06.2012, 01:57

Я все же по поводу сортировки по вычесляемому полю. Я так понял, она делается через свой хендлер. Прочитал у gaker'a что в качестве хендлера нужно указывать

'sort' => array(
      'handler' => 'views_handler_sort_formula',
      'formula' => 'ROUND(testnode.int_count*100/testnode.int_total)',
    ),

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

Гость
18.08.2012, 09:50

В views 3 как сделать не поможете

Во Views 3 и правда не пашет. Хотя ошибки не выдает.

Сергей
26.06.2014, 18:35

Подскажите, каким образом можно округлить результат?

Михаил
24.07.2016, 00:40

Да, для семерки пример с сортировкой и подсчетом пригодился бы.

"Пример field хэндлера для Views 3" - сдохла ссылочка, нет возможности обновить?

Добавить комментарий