Как изменить запрос представления после изменения открытого фильтра?
У нас есть пользовательское представление myview
, которое имеет два открытых фильтра: country
и category
. Для значения country
у нас есть значение, которое мы хотим применить, независимо от того, что выбрано в качестве открытого фильтра, который не является All Countries
.
Как бы мы изменили запрос после выбора значения, чтобы мы всегда добавляли or country = United States of America
к любому значению, выбранному для запроса представления?
Цель:
После применения открытого фильтра измените запрос такой, чтобы он возвращал все, что выбрал пользователь, И все остальные узлы, где country = 'United States'
.
Значение страны:
- Все страны
- По всему миру
- Соединенные Штаты Америки
- Соединенное Королевство
- Франция
- Германия
Что мы думали использовать 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);
}
}
Текущие фильтры:
- опубликовано = да
- тип контента = статья
- страна (открытый фильтр, отобразить все, выбрать один)
- категория (открытый фильтр, отобразить все, выбрать один)
При использовании ksm()
для печати $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'))
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 со снимка экрана:
Взято из примера с крючком. Предполагая, что ваше имя фильтра поле-страна возможным решением может быть:
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',
];
}
}
}
}
}
Я еще не полностью протестировал его, но он должен работать.
Также вы всегда можете реализовать свой собственный специальный плагин фильтра.
Обновление: Добавьте условие, чтобы проверить, является ли фильтр многозначным.
Обновление: Удалите строгое сравнение для входного значения фильтра, так как это может вызвать побочные эффекты.