CMS Drupal

Очередной свой сайт решил сделать как можно меньше прибегая к собственным модулям. Поэтому создавая форму поиска пришлось повозиться с views, т.к. поиск был не самым простым.
В частности сложность возникла в следующем.

На сайте пользователи вбивают информацию о месте отдыха(тип материала rest_place). Для места отдыха указывается тип минеральной воды, которая там есть(если она вообще там есть). А в форме поиска захотелось сделать просто переключатель для выбора есть там вообще минеральная вода или нет, т.е. без выбора видов воды. Было бы отдельное CCK-поле с нулем или единицей, то проблем бы не было, но в данном случае такого поля нет.

Сначала я подумал о варианте, чтобы все таки завести такое поле и пихать в него 0 или 1 из хука nodeapi. Но потом все таки решил поковырять views. Вот коротко что я сделал:

К своему модулю "alex_module" добавил файл alex_module.views.inc

function alex_module_views_data() {
  $data = array();
 
  $data['node']['mineral_water'] = array(
    'title' => t('Mineral water'),
    'field' => array(
      'handler' => 'alex_module_handler_field_mineral_water',
    ),
    'help' => 'n/a',
    'filter' => array(
      'handler' => 'alex_module_handler_filter_mineral_water',
    ),
  );
  return $data; 
}
 
function alex_module_views_handlers() {
  $handlers = array();
 
  $handlers['handlers']['alex_module_handler_field_mineral_water'] = array(
    'parent' => 'views_handler_field_boolean',
    'file' => 'views_handlers/alex_module_handler_field_mineral_water.inc',
  );
  $handlers['handlers']['alex_module_handler_filter_mineral_water'] = array(
    'parent' => 'views_handler_filter_boolean_operator',
    'file' => 'views_handlers/alex_module_handler_filter_mineral_water.inc',
  );
  $handlers['handlers']['alex_module_handler_relationship_content'] = array(
    'parent' => 'views_handler_relationship',
    'file' => 'views_handlers/alex_module_handler_relationship_content.inc',
  );
 
  return $handlers;
}
 
function alex_module_views_data_alter(&$data) {
  // Чтобы в появилось в разделе relationship
  $data['node']['bunsen'] = array(
    //'group' => 'node',
    'title' => t('Rest place'),
    'help' => 'n/a',
    'real field' => 'vid',
    'relationship' => array(
      'handler' => 'alex_module_handler_relationship_content',
      'base' => 'node',
      'field' => 'vid',
    )
  );
}

Описывая данный код можно сказать, что добавил новое поле (виртуальное), т.е. поле, которого физически нет ни у одной таблицы. Добавил обработчики для поля, фильтра и соединения с таблицей content_type_rest_place. Именно соединение вызвало у меня больше всего сложностей.
Т.к. виды минеральной воды - это поле CCK, то для правильной фильтрации необходимо к ноде присоединить таблицу content_type_rest_place.
Сам обработчик связывания таблиц (alex_module_handler_relationship_content.inc) выглядит так:

class alex_module_handler_relationship_content extends views_handler_relationship {
  function query() {
    $def = $this->definition;
    $def['table'] = 'content_type_rest_place';
    $def['field'] = 'vid';
    $def['left_table'] = 'node';
    $def['left_field'] = 'vid';
    $join = new views_join();
    $join->definition = $def;
    $join->construct();
    $join->adjusted = TRUE;
 
    // use a short alias for this:
    $alias = $def['table'] . '_' . $this->table;
 
    $this->alias = $this->query->add_relationship($alias, $join, $this->definition['base'], $this->relationship);
  }
}

А обработчик фильтрации так:

class alex_module_handler_filter_mineral_water extends views_handler_filter_boolean_operator {
  function query() {
    $this->ensure_my_table();
 
    if (empty($this->value)) {
    }
    else {
      $where = "content_type_rest_place_node.field_mineral_water_ext_value<>0 OR content_type_rest_place_node.field_mineral_water_int_value<>0";
 
      $this->query->add_where($this->options['group'], $where);
    }
  }
 
  function get_value_options() {
    $this->value_options = array(1 => t('Yes'));
  }
 
}

Попутно в функции get_value_options я избавился от опции "N0", чтобы в форме поиска для нашего виртуального поля "Наличие минеральных вод" можно было выбрать либо Any(Не важно), либо "Да".

Комментарии

Выберите нужный метод показа комментариев и нажмите "Сохранить установки".

Уж если отходить от самописок, то было бы правильней использовать computed_field, в которое сувалось бы 0 или 1 в зависмости есть вода или нет, или сделать тоже самое при помощи модуля rules - он погибче чем computed_field.
Но все равно клево! :)

admin аватар

Признаться, мне просто под руки не попался computed_field. Щас гляжу на него, на кучу снипетов для него и не понимаю как я его не заметил. Из пушки по воробьям палил получается. Ну ладно, в следующий раз его попробую.

Ситуация просто комедия!!! :)

Читаю статью - все классно написано, элегантное решение, дальше читаю комменты: чувак критикует предлагает computed_field. Я негодую! Вот думаю урод - узнал пару модулей и критикует программиста! Щас думаю напишу коммент - смотрю имя урода, а это Я! Написал этот коммент больше года назад :)))

Отличная статья! Спасибо!

P.S. Computed field сейчас не использую, на крайняк, если нужно быстренько что-нибудь соорудить, добавляю обычное поле и пишу правило для Rules, которым его заполняю, более гибкий вариант. А так модули и только модули :)

admin аватар

У меня самого пару раз было так, что в поисковике находил свой же сайт и читал свои же статьи так, как будт-то и не я писал. При этом находя ответы на возникшие вопросы.

Ребята пиво - хорошо, но надо в меру!!!

Отправить комментарий

Содержание этого поля является приватным и не предназначено к показу.
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Доступны HTML теги: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <img>
  • Строки и параграфы переносятся автоматически.
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>, <1c7>, <drupal5>, <drupal6>, <javascript>, <php>. Beside the tag style "<foo>" it is also possible to use "[foo]".