• Как отфильтровать ноды по дате без учета года с помощью Views в Drupal 7?

    @NoMax Автор вопроса
    В общем, всё остальное было от лукавого и левыми путями решения - реально, что помогло - это реализация хука mymodule_views_query_alter()

    ниже будет много букв - мало доступной инфы в интернетах по поставленному вопросу, если кто-то вновь с таким столкнётся - надеюсь, ему поможет моя попытка пояснить что и с чем тут едят.

    много времени было потрачено на поиск легких путей решения - через обычные фильтры views, контекстные фильтры, поиск годного модуля, попытка реализовать фильтр с помощью модуля Views PHP - однако, легкого и простого сравнения не получалось реализовать. пытался зацепиться за форматы дат, и сравнение по дню года, но потом отсёк данный вариант т.к. есть високосные года, которые смещают соответствие. костыли к этому крутить не хотелось. Обратился к великому и могучему SQL, нарвался на его функцию DATE_FORMAT(), которая позволяла вывести и сравнить дату в нужном мне формате. Вот тут-то и решил, что получать сразу нужную выборку будет гораздо кошернее, чем заниматься fetch-ингом и подобным. Составил тестовый SQL-запрос, проверил - работает. Причём работает именно так, как нужно:
    select eor_node.nid, eor_node.title from eor_node, eor_field_data_field_birthday where eor_node.nid=eor_field_data_field_birthday.entity_id and DATE_FORMAT(eor_field_data_field_birthday.field_birthday_value,'%d-%m')=DATE_FORMAT(NOW(),'%d-%m') order by DATE_FORMAT(eor_field_data_field_birthday.field_birthday_value,'%d')

    есть таблица с нодами, есть таблица поля, которое хранит дату. между этими таблицами есть связь - каждое поле даты связано с определенной записью в таблице нод, для которой оно создано.
    забираем id ноды и её заголовок из таблицы с нодами где есть связка нода-поле и форматированная дата (день-месяц) равна форматированной дате сегодняшнего дня

    теперь оставалось самое интересное - изменить sql-запрос, который формирует views.

    В общем, как и было предложено на просторах гугла - создал свой модуль добавил эту чудесную функцию, немного потупил с тем, как вносить правки в запрос, наткнулся на некоторые особенности, но их удалось победить. Справочной и полноценной инфы как конкретно добавлять/менять условия sql-запроса для views я не нашёл (может плохо искал). моим ориентиром были обрывочные примеры кода из найденных в интернете реализаций, абстрактное понятие как это может работать с точки зрения программирования и метода научного тыка.

    Источники из интернетов предлагали использовать DEVEL и dpm(), но у меня как-то не сложилось с таким представлением отладки. помог сам модуль Views, а точнее пунктик в его настройках (структура->представления->настройки). Замечательный чек-бокс аля "Показывать SQL-запрос в представлении" помог мне отладить новоиспеченный модуль и не работать вслепую".

    Теперь в окне редактирования представления ниже функциональных инструментов появился блок, выводящий SQL-запрос, формирующийся для вьюхи. Дальше пошло самое интересное - попытки научного тыка правильно добавлять условия в SQL-запрос вьюхи. Метода была такая: Правим код в файле модуля с хуком, сохраняем, переходим в браузер и жмакаем в окне редактирования вьюхи "предосмотр", чтобы увидеть формируемый SQL-запрос и ниже результат выборки. В общем все итерации научного тыка отложу, а приведу код, который "взлетел":
    function myhook_views_query_alter(&$view, &$query) {
      if ($view->name == 'persons') {
        //добавляем в запрос таблицу, в которой хранятся поля с датой рождения
        $query->add_table('field_data_field_birthday');
       //добавляем условие, что день и месяц в дате рождения именинника должен совпадать с сегодняшним днем и месяцем
        $query->add_where_expression('AND',"DATE_FORMAT(field_data_field_birthday.field_birthday_value,'%m')=DATE_FORMAT(NOW(),'%m')");
       //условие взаимосвязи записей из таблицы нод и поля, хранящего даты ДР
        $query->add_where_expression('AND',"nid=field_data_field_birthday.entity_id");
      }
    };


    методом научного тыка выявлено:
    • при добавлении таблицы в запрос с помощью $query->add_table() префикс таблицы в бд писать не нужно;
    • чаще встречающееся в примерах использование конструкции для добавления where-условия в запрос $query->add_where() в данном случае невозможно - она парсит значения, режет скобки и служебные символы функций SQL - тем самым "портит" запрос, поэтому используется конструкция add_where_expression(), которую советуют не сильно использовать, но она реально работает и не портит компоненты запроса.


    честно говоря, так глубоко в drupal я раньше не погружался, но рад, что всё же смог решить поставленный вопрос, который изначально вообще не виделся проблемным. полученная инфа для решения вопроса собиралась по крохам из других примеров. как обращаться с $query и какие конструкции к нему применять - единого и полноценного источника справочной инфы не нашёл, всё лишь багаж личных знаний и примерное понимание как это может работать. ещё смущает, что пока конструкция if ($view->name == 'persons') видоизменяет запрос для всего представления, а не для его конкретного блока или страницы - буду искать как это решить.

    Всем спасибо за советы, отдельное спасибо xandeadx - не дал решения, но намекнул в какую сторону копать)

    p.s.: анализ print_r($query) дал ответ как зацепиться за конкретный отдельный блок или страницу преставления. для этого нужно использовать машинное имя этой текущей конструкции. зацепиться за неё можно с помощью $view->current_display. в моем случае получилось так:
    if ($view->name == 'persons' && $view->current_display == 'block1')  {
    //...
    };
    Ответ написан
    Комментировать