Очередной свой сайт решил сделать как можно меньше прибегая к собственным модулям. Поэтому создавая форму поиска пришлось повозиться с 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.
Но все равно клево! :)
Признаться, мне просто под руки не попался computed_field. Щас гляжу на него, на кучу снипетов для него и не понимаю как я его не заметил. Из пушки по воробьям палил получается. Ну ладно, в следующий раз его попробую.
Ситуация просто комедия!!! :)
Читаю статью - все классно написано, элегантное решение, дальше читаю комменты: чувак критикует предлагает computed_field. Я негодую! Вот думаю урод - узнал пару модулей и критикует программиста! Щас думаю напишу коммент - смотрю имя урода, а это Я! Написал этот коммент больше года назад :)))
Отличная статья! Спасибо!
P.S. Computed field сейчас не использую, на крайняк, если нужно быстренько что-нибудь соорудить, добавляю обычное поле и пишу правило для Rules, которым его заполняю, более гибкий вариант. А так модули и только модули :)
У меня самого пару раз было так, что в поисковике находил свой же сайт и читал свои же статьи так, как будт-то и не я писал. При этом находя ответы на возникшие вопросы.
Ребята пиво - хорошо, но надо в меру!!!
Отправить комментарий