web-dev-qa-db-ja.com

公開されたフィルターが変更された後にビュークエリを変更する方法は?

myviewcountryの2つの公開フィルターを持つカスタムビューcategoryがあります。 country値には、_All Countries_ではない公開フィルターとして何が選択されているかに関係なく適用したい値があります。

値が選択された後にクエリを変更して、ビューのクエリで選択された値に常に_or country = United States of America_を追加する方法を教えてください。

目標:

公開されたフィルターが適用されたら、ユーザーが選択したものと、_country = 'United States'_の他のすべてのノードが返されるようにクエリを変更します。

国の値:

  1. 全ての国々
  2. 世界的に
  3. アメリカ合衆国
  4. イギリス
  5. フランス
  6. ドイツ

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);
  }

}
_

現在のフィルター:

  1. 公開済み=はい
  2. コンテンツタイプ=記事
  3. 国(公開フィルター、すべて表示、単一選択)
  4. カテゴリー(公開フィルター、すべて表示、単一選択)

ksm()を使用して_$condition_group_を出力すると、これが結果になります。 2つの露出したフィルターも表示されていません。 condition group

現在の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'))
_
2
usernameabc

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

2
usernameabc

フックの例から取ったものです。フィルター名が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:フィルターが複数値かどうかを確認する条件を追加します。

更新:副作用を引き起こす可能性があるため、フィルター入力値の厳密な比較を削除します。

1
d70rr3s