Как изменить запрос представления после изменения открытого фильтра?


У нас есть пользовательское представление myview, которое имеет два открытых фильтра: country и category. Для значения country у нас есть значение, которое мы хотим применить, независимо от того, что выбрано в качестве открытого фильтра, который не является All Countries.

Как бы мы изменили запрос после выбора значения, чтобы мы всегда добавляли or country = United States of America к любому значению, выбранному для запроса представления?

Цель:

После применения открытого фильтра измените запрос такой, чтобы он возвращал все, что выбрал пользователь, И все остальные узлы, где country = 'United States'.

Значение страны:

  1. Все страны
  2. По всему миру
  3. Соединенные Штаты Америки
  4. Соединенное Королевство
  5. Франция
  6. Германия

Что мы думали использовать hook_views_query_alter, но не уверены, как мы можем изменить запрос после выбора значения.

Mymodule.модуль

use Drupal\views\ViewExecutable;
use Drupal\views\Plugin\views\query\QueryPluginBase;

/**
 * Implements hook_views_query_alter().
 */
function mymodule_views_query_alter(ViewExecutable $view, QueryPluginBase $query) {

  if ($view->id() == 'myview') {
    $or_statement = new Condition('OR');
    $or_statement->condition('field_country', '12', '=');
    $query->addWhere(0, $or_statement);
  }

}

Текущие фильтры:

  1. опубликовано = да
  2. тип контента = статья
  3. страна (открытый фильтр, отобразить все, выбрать один)
  4. категория (открытый фильтр, отобразить все, выбрать один)

При использовании ksm() для печати $condition_group, это результаты. Он даже не показывает два открытых фильтра. condition group

Текущее предложение Where

10 является значение, выбранное пользователем из открытого фильтра и 12, является тем, которое мы хотим добавить.

WHERE (((node__field_country.field_country_target_id = '10')) AND (node__field_country.field_country_target_id = '12'))

Желаемый пункт "где"

WHERE (((node__field_country.field_country_target_id = '10')) OR (node__field_country.field_country_target_id = '12'))
Author: usernameabc, 2018-07-31

2 answers

Используя предложение d70rr3s и этот патч (требуется), я наткнулся на это решение, которое сработало.

use Drupal\views\ViewExecutable;
use Drupal\views\Plugin\views\query\QueryPluginBase;

/**
 * Implements hook_views_query_alter().
 */
function mymodule_views_query_alter(ViewExecutable $view, QueryPluginBase $query) {
   if ($view->id() == 'myview'  && !empty($view->exposed_raw_input['field_country']) && $view->exposed_raw_input['field_country'] !== 'all') {
    // Traverse through the 'where' part of the query.
    foreach ($query->where as &$condition_group) {
      foreach ($condition_group['conditions'] as &$condition) {
        if ($condition['field'] == 'your_entity.field_country') {
          $field = 'node__field_country.field_country_target_id';
          $value = 'somevalue';
          $operator = '=';
          $query->addWhere(2, $field, $value, $operator);
        }
      }
    }
  }
}

Результаты:

WHERE (((node__field_country.field_country_target_id = '10')) OR (node__field_country.field_country_target_id = 'someValue')) AND (node_field_data.status=1) AND (node_field_data.type='article')

Критерии фильтрации, к которым нужно было применить #1 и #2 со снимка экрана:

filter criteria

 3
Author: usernameabc, 2018-08-02 20:12:27

Взято из примера с крючком. Предполагая, что ваше имя фильтра поле-страна возможным решением может быть:

use Drupal\views\ViewExecutable;
use Drupal\views\Plugin\views\query\QueryPluginBase;

/**
 * Implements hook_views_query_alter().
 */
function mymodule_views_query_alter(ViewExecutable $view, QueryPluginBase $query) {
   if ($view->id() == 'myview'  && !empty($view->exposed_raw_input['field_country']) && $view->exposed_raw_input['field_country'] != 'all') {
    // Traverse through the 'where' part of the query.
    foreach ($query->where as &$condition_group) {
      foreach ($condition_group['conditions'] as &$condition) {
        if ($condition['field'] == 'your_entity.field_country') {
           $filter_value = $view->exposed_raw_input['field_country'];
           if (!is_array($filter_value)) {
             $filter_value = [$filter_value];
           }

           $condition = [
             'field' => 'your_entity.field_country',
             'value' => array_merge($filter_value, ['United States Of America']),
             'operator' => 'IN',
           ];
        }
      }
    }
  }
}

Я еще не полностью протестировал его, но он должен работать.

Также вы всегда можете реализовать свой собственный специальный плагин фильтра.

Обновление: Добавьте условие, чтобы проверить, является ли фильтр многозначным.

Обновление: Удалите строгое сравнение для входного значения фильтра, так как это может вызвать побочные эффекты.

 1
Author: d70rr3s, 2018-08-02 01:09:36