myview
とcountry
の2つの公開フィルターを持つカスタムビューcategory
があります。 country
値には、_All Countries
_ではない公開フィルターとして何が選択されているかに関係なく適用したい値があります。
値が選択された後にクエリを変更して、ビューのクエリで選択された値に常に_or country = United States of America
_を追加する方法を教えてください。
目標:
公開されたフィルターが適用されたら、ユーザーが選択したものと、_country = 'United States'
_の他のすべてのノードが返されるようにクエリを変更します。
国の値:
hook_views_query_alter を使用して考えていたものですが、値が選択された後にクエリを変更する方法はわかりません。
mymodule.module
_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
_を出力すると、これが結果になります。 2つの露出したフィルターも表示されていません。
現在のWhere句
_10
_は公開されたフィルターからユーザーが選択した値で、_12
_は追加したい値です。
_WHERE (((node__field_country.field_country_target_id = '10')) AND (node__field_country.field_country_target_id = '12'))
_
必要なwhere句
_WHERE (((node__field_country.field_country_target_id = '10')) OR (node__field_country.field_country_target_id = '12'))
_
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を適用する必要があるフィルター基準:
フックの例から取ったものです。フィルター名がfield-countryであるとすると、考えられる解決策は次のようになります。
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',
];
}
}
}
}
}
私は完全にはテストしていませんが、動作するはずです。
また、いつでも独自の アドホックフィルタープラグイン を実装できます。
Update:フィルターが複数値かどうかを確認する条件を追加します。
更新:副作用を引き起こす可能性があるため、フィルター入力値の厳密な比較を削除します。