web-dev-qa-db-ja.com

プログラムでビューにFILTER CRITERIAを追加する

プログラムでfilter criteriaを追加/変更したい。

たとえば、ビューの場合、値を動的に変更するために必要な「メールアドレス」フィルターを追加しました。このフィルターは、現在ログインしているユーザーのメールIDに設定する必要があります。

それを達成する方法は?詳細は添付画像をご覧ください。助けてください。

enter image description here

18
Shafiul

写真の「value」フィールドに「[email protected]」のように入力した後、 Devel モジュールとdpm($view)dpm($query)を使用します。ビューのオブジェクト/配列構造を確認し、devel出力からクエリを実行します。

次に、モジュールで関数hook_views_query_alter(&$view, &$query)を使用してWHERE条件フィルター条件をターゲットにし、それを必要な値に設定します。

何かのようなもの:

function MYMODULE_views_query_alter(&$view, &$query) {
  global $user;
  dpm($view, __FUNCTION__);
  dpm($query, __FUNCTION__);
  if ($view->name === 'your_view_machine_name') {
    // This will only work as-is if you always have something in the filter by
    // default, I guess. This hook runs always so you could just put
    // '[email protected]' as the email to filter by in views and this
    // will always override it. I'm sure there is a cleaner way to put
    // the filter dynamically at runtime. But i think thats more complex
    // php that customizes a view.
    //
    // The index 2 below is the index of the condition for the email filter.
    // Your $query structure may be different in your dpm() of the View $query.
    $query->where[1]['conditions'][2]['field']['value'] = $user->email;
  }
}
25
tenken

ここに代替があります:

$view = views_get_view('view_machine_name');
$view->init_display('default');
$view->display_handler->display->display_options['filters']['your_filter_name']['default_value'] = 'your_value';
$view->is_cacheable = FALSE;  
$view->execute();
print $view->render();

おそらく、難解で複雑な方法を使用してこれを設定する必要がありますが、混乱しないで迅速かつダーティなアクセスが必要な場合は、これでそこに到達します。

7
rix

サイトのパフォーマンスとキャッシュを損なうことがないように、レンダリング時ではなくフックでこれらを変更することをお勧めします。 hook_views_pre_build() の起動が遅すぎることを理解するために年齢をとるには、 hook_views_pre_view() が必要です。

$ view-> add_item() の使用への参照を見つけましたが、例に苦労しました。以下は、特定の語彙のみを含めるように分類用語のセットをフィルタリングするための私の解決策です:

function MODULENAME_views_pre_view(&$view, &$display_id, &$args) {

  if ($view->name == 'VIEWNAME' && $display_id == 'DISPLAYID') {
    // Add all the terms of a vocabulary to the terms listing widget select field
    $vids = array();
    $vocab = taxonomy_vocabulary_machine_name_load('vocab_name');
    $vids[ $vocab->vid ] = $vocab->vid;

    // Get the existing filters
    $filters = $view->display_handler->get_option('filters');

    if (empty($filters['vid'])) {
      // There is no vid filter so we have to add it
      $view->add_item(
        $view->current_display,
        'filter',
        'taxonomy_term_data',
        'vid',
        array(
          'operator' => 'in',
          'value' => $vids,
          'group' => 1
        )
      );
    }
    else {
      // Add to pre-existing filter
      foreach($vids as $vid) {
        $filters['vid']['value'][ $vid ] = $vid;
      }
      $view->display_handler->override_option('filters', $filters);
    }
  }
}

Edit noteこのコメント on do groupは、$view->display_handler->get_option('filters')を使用してビューフィルターを取得する方法を理解するのに役立ちましたそして、$view->display_handler->override_option('filters', $filters);を使用してそれらを上書きします。

6
Duncanmoo

同様の問題がありましたが、フィルターに複数の引数を渡そうとしました。 「views_get_view」メソッドを使用しましたが、ビューに引数を渡しました。誰かのお役に立てば幸いです。必要に応じて、引数のタイプまたは値を置き換えることができます。

(詳細ビュー設定フィールドセットから)ビュー自体にコンテキストフィルターを追加しました。 1つ目は「コンテンツ:分類用語IDがあります」です。 2つ目は、「content:nid」で、「allow multiple」がチェックされ、「exclude」チェックボックスがチェックされています(コンテキストフィルターポップアップの「more」フィールドセットから)。

 args [] = '1'; //用語ID 
 args [] = '1 + 2 + 3'; // Node除外/含めるID 
 
 $ view = views_get_view($ view_name); 
 $ view-> init(); 
 $ view-> set_display($ display); 
 $ view-> set_arguments($ args); 
 $ view-> execute(); 
 $ view- >結果

更新:コンテキストフィルターの値の中で、phpコードを選択して渡されたビュー引数を返す必要がある場合があることを忘れていました。例:

 return $ view-> args [1]; 
3
Seb

Drupal 8では、ViewExecutable::setHandler($display_id, $type, $id, $item)を使用してプログラムでフィルターを設定できます。

2
vlledo

Drupal 8にプログラムでフィルター基準を追加する方法の例を次に示します。

/**
 * @param ViewExecutable $view
 * @param QueryPluginBase $query
 *
 * Sets a custom custom filter criteria (takes current language into account)
 */
function MODULE_views_query_alter(ViewExecutable $view, QueryPluginBase $query) {
  if ($view->storage->id() === 'my_view_id') {
    $query->addWhere(0, 'node__field_custom_criteria.field_custom_criteria_value', \Drupal::languageManager()->getCurrentLanguage()->getId(), '=');
  }
}

上記のクエリは、field_custom_criteriaフィールドは、現在選択されている言語と同じです。

詳細はドキュメントにあります: hook_views_query_alter

1
estrar

最高だと感じた@ Duncanmoo上記の回答 に基づいて、次のフィルターを自分のビューに追加しました。参照された分類法に基づいて、代わりに参照されたエンティティまたはNIDに基づいてフィルタリングするには:

function [MYMODULE]_views_pre_view(&$view, &$display_id, &$args) {
  if (($view->name == '[your view name]') && ($display_id == '[your display id]')) {
    // Get referenced service - example for entity reference.
    $node = menu_get_object();
    $node_wrapper = entity_metadata_wrapper('node', $node->nid);
    $referenced_service = $node_wrapper->field_service_ref->value();
    // Add service id as a filter to view.
    $filters = $view->display_handler->get_option('filters');
    if (empty($filters['field_service_ref_target_id'])) {
      // Only display operations nodes that reference the same service.
      $view->add_item(
        $display_id,
        'filter',
        'field_data_field_service_ref',
        'field_service_ref_target_id',
        array(
          'operator' => '=',
          'value' => ['value' => $referenced_service->id],
          'group' => 1
        )
      );
    }
    // Add nid as a filter to view - example for NID filter
    if (empty($filters['nid'])) {
      // Don't include current operation in list of related operations.
      $view->add_item(
        $display_id,
        'filter',
        'node',
        'nid',
        array(
          'operator' => '!=',
          'value' => ['value' => $node->nid],
          'group' => 1
        )
      );
    }
  }
}
1
kbrinner