xandeadx.ru Блог музицирующего веб-девелопера

Drupal → Сложные фильтры в Views, способ 1

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

Иногда бывает нужно сделать какую-нибудь хитрую выборку, которую с помощью обычных фильтров Views сделать невозможно. Например у меня появилась задача вывести новости, го́да создания которых нет в меню. Т.е. есть меню с пунктами 2011, 2010, 2009, и надо вывести новости, которые были созданы не в 2011, 2010, 2009 годах. Эдакий архив.

Сделать это можно следующим образом:

Добавляем контекстный фильтр (Contextual filters, в Views 2 это называлось аргументами) по полю Content: Nid:

Форма добавления контекстного фильтра

В блоке When the filter value is NOT in the URL отмечаем опцию Provide default value и выбираем тип PHP Code:

Настройки контекстного фильтра

Ниже, в поле PHP contextual filter code пишем php код, который должен вернуть идентификаторы материалов объединённых символом +:

Настройки контекстного фильтра

И последним шагом, в блоке More, отмечаем опцию Allow multiple values:

Настройки контекстного фильтра

Profit.

Сложные фильтры в Views, способ 2 — пишем свой filter handler

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

Комментарии RSS

Жаль для сортировки нельзя PHP использовать :)

есть модуль Views PHP, он умеет

По нему бы мануальчик, было бы не плохо

Как сделать выборку нод,где автор ноды=юиду пользователя,который смотрит на выборку вьюса?
тоесть пользователи создают ноды и вьюс им должен показывать список их нод.

добавить фильтр по User: Current

Блин, ерунда какая-то... попробовал сделать тоже самое для Друпал 6, View 3 . Пол дня убил ничего не получается.

watchdog('php', 'View node Start');
$result = db_query("SELECT * FROM {node}");
$nids = array();
foreach ($result as $row) {
  watchdog('php', 'View node NID ');
  $nids[] = $row->nid;
}
return implode('+', $nids);

(в оригинале запрос конечно сложнее, но упростил его, чтобы просто заработало)
Похоже $result пустой, т.к. в лог ничего не пишется. Непонятно, db_query не отрабатывает?
Явно туплю и не пойму в чем. Да, если возвращаю тупо return '259' - все Ок.

while ($row = db_fetch_object($result)) {
  watchdog('php', 'View node NID ');
  $nids[] = $row->nid;
}

Оперативно! Спасибо. Буду эксперементировать.

Огромное спасибо! Прям протащили меня за руку через эту проблему, решил все быстро и без потерь времени. Спасибо!

Вы не подскажете, можно ли во Views создать несколько блоков фильтров для одного представления (хочется иметь детальный фильтр и короткий фильтр на главной)? Пока только приходит в голову использовать один и тот же блок, но скрывать часть полей css или form_alter.

думаю что нет. hook_form_alter

Спасибо!

А как отлаживать код PHP? Как посмотреть какие данные есть в переменных? Как посмотреть в конце концов, какие переменные доступны для контекстного фильтра?

Не помню раньше вроде получалось, а сейчас не могу найти.
Мне надо например тупо в виевсе вывести ноды с nid IN (10,20,30).
Так как в статье написано с помощью контекстного оно получится.
Но разве обычные фильтры такое не делают?
Начал добавлять сейчас фильтр Содержимое:Nid оно жесткое равенство или сравнение предлагает со значением.
Я точно помню раньше когда с виевсом разбирался где то в его настройке было такое что указываешь список чего то и радио типа IN или NOT IN.
Подскажете?

views_handler_filter_numeric не поддерживает IN

Жаль.
Нашел в админке сейчас где такой ввод - там где тип материала и там где фиелды типа список.

Спасибо за пост! Искал вчера весь день, а сегодня первая ссылка) Очень нужная вещь

А если вьюху выводит термины таксономии у которых есть такие поля как RAZDEL (Term) и STATUS (List text)
по умолчанию вьюха выводит с аргументом в виде машинного имени поля RAZDEL, но теперь нужно ещё вдобавок вывести со втором аргументом STATUS, он он у меня к сожалению в виде списка, и поэтому друпал не предлагает его машинное имя использовать как контекст, только самое поле, а значения у него кириллица. И поменять то уже нельзя на аналогичный первому - в виде термина.

т.е. как можно сделать двойной аргумент, первый который смотрит на машинное имя, и второй тоже машинное имя (ведь оно есть у списка) но в виде списка текстового

А как сделать в фильтре взаимосвязь между полями разных таблиц, участвующих в запросе? PHP код не дает доступа к полям других таблиц в условии WHERE. Думал, поможет модуль Views Custom Conditions, но там тоже указывается таблица заранее, из которой, похоже, вначале идет выборка. Но это не то. Смотрел Views PHP, Views Raw SQL и прочее, но там такого нет.
Поля у меня доступны в фильтрах, но не знаю, как указать связи между ними < (меньше) и > (больше).

$query->leftJoin
$query->innerJoin
$query->rightJoin

Таблицы-то уже соединены через отношения. Или нужно написать модуль, который будет в некоем хуке делать эти join'ы? У меня в этом SQL используется агрегация, так что на результат запроса нельзя просто так наложить join... Вижу только выход - весь запрос писать руками. Нет ли другого способа? Ибо зачем тогда Views.

запрос в контекстных фильтрах не имеет никакого отношения к Views

Спасибо за внимание к моей проблеме. Но всё же где эти join'ы прописывать в контекстном фильтре?

Спасибо, я видел это. Но ведь тут другой случай. Всякие_хитрые_условия из картинки не могут использовать поля из участвующих в запросе таблиц. Эти условия таковы, что поля одной таблицы должны сравниваться с полями другой таблицы в самом SQL-запросе. А уже строки этой другой таблицы фильтруются штатными средствами Views.

пишите свои хэндлеры

Подскажите, каким образом можно вывести материал в запросе по какому-либо полю связывающему 2 разных типа материала? Имеется ввиду по аналогии с контекстными фильтрами, только php код.

Спасибо за Ваш пост очень помог

Наверно вопрос совсем ниже плинтуса.
А как сделать меню с пунктами [2011, 2010, 2009] года соответственно из "Content: Post date" ? Нужно сделать меню средствами views пункты которых есть года постов с ссылками на архив года (но это детали).

У меня вопросик:
Сделал я вьюс и хочу проверить на странице ноды - будет ли эта нода отображаться в этом вьюсе? Проходит ли эта нода фильтры? Просто вьюху сделать проще, чем запрос к базе писать...

Добрый день.
А не подскажете, возможно ли в контекстных фильтрах использовать диапазон значений, ну или хотя бы >=, либо <=?

Привет! Поймал мистическую ситуацию.
вот PHP код в контекстном фильтре:

$nids = db_query('SELECT n.nid FROM {node} as n WHERE n.type = :type and n.title REGEXP :regexp', array(':type' => 'product', ':regexp' => '[a-zA-Z]'))->fetchCol();
return implode('+', $nids);

в dev/php работает нормально http://i.imgur.com/6AQqlqB.png
а в контекстном фильтре Error 500 End of script output before headers: php

Без return implode('+', $nids); ошибки нет. Что может быть?

PS: при том аналогичный запрос работает:

$nids = db_query('SELECT n.nid from {node} as n INNER JOIN (SELECT title from {node} GROUP BY title HAVING COUNT(*) > 1) as n2 ON n.title=n2.title')->fetchCol();
 
return implode('+', $nids);

Добавил LIMIT - ошибка пропала.
без лимита выборка 15077строк
теперь вопрос, как обойтись без лимита?

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

Содержимое этого поля является приватным и не будет отображаться публично. Если у вас есть аккаунт в Gravatar, привязанный к этому e-mail адресу, то он будет использован для отображения аватара.
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Доступные HTML теги: <a> <i> <b> <strong> <code> <ul> <ol> <li> <blockquote> <em> <s>
  • Строки и параграфы переносятся автоматически.
  • Подсветка кода осуществляется с помощью тегов: <code>, <css>, <html>, <ini>, <javascript>, <sql>, <php>. Поддерживаемые стили выделения кода: <foo>, [foo].

Подробнее о форматировании