【Drupal】Contextual Filterの設定方法 Step-by-Step Guide

前回に引き続き、「**Contextual Filter**」シリーズです。

今回は **How To編** です。

このシリーズでは三記事に渡って、「Contextual Filter ってなに？」「設定方法」「実践」をご紹介します。

## 準備
### 1. 事前にDrupal環境を用意してください
https://qiita.com/umekikazuya/items/5b6069cd7a868bf74f3c

### 2. NodeをBaseTableにしたViewsを作成してください
![スクリーンショット 2024-06-16 2.41.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334980/583a734a-2104-f336-2f02-b144293ece12.png)
## 静的フィルタリング設定
### まずはコンテンツを「掲載のみ」でフィルタリングをしてみましょう
「掲載」は真偽値のため、「0・1」でデータが登録されています。

固定値の箇所に、「1」を入力します。

![2024-06-16.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334980/77cc01fb-20c4-b0fd-6df4-10db64f8cb50.gif)

クエリとプレビューを見てみましょう。

![スクリーンショット 2024-06-16 0.50.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334980/8e089187-9a4f-2aa9-0aea-8b8a4e7ea939.png)


```sql
WHERE (node_field_data.status = '1')
```

いい感じですね。

### コンテンツを「掲載以外」でフィルタリングをしてみましょう
今度は、「掲載以外」のもの表示してみましょう。「※非掲載のみではないのがミソ」

設定画面内に「除外」って項目があるのでそちらを使ってみましょう。（固定値は「1」のまま）

![スクリーンショット 2024-06-16 2.10.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334980/bcd191cc-f62a-4aac-91e8-9e2ead7e326a.png)


クエリとプレビューを見てみましょう。

```sql
WHERE (node_field_data.status != '1' OR node_field_data.status IS NULL)
```

もうお気づきでしょうか？

**「0」で引っ掛けているのではなく、データが空の場合も含めるようにクエリを作ることができます。**

### 次は複数のArgumentで絞り込みをしてみましょう

バンドルが「記事(article)」「News(news)」「ブログ(blog)」のコンテンツの一覧を作ります。

「複数の値を許可する」とあるのでチェックを入れてください。

![スクリーンショット 2024-06-16 2.13.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334980/f8285f2d-f78c-a154-dd8b-865d01a9edbb.png)

固定値の入力値に「article+news+blog」と入力します。

![スクリーンショット 2024-06-16 2.15.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334980/db743292-1f91-3932-91f1-684e80f3ffff.png)

クエリとプレビューを見てみましょう。

![スクリーンショット 2024-06-16 1.08.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334980/4e1fde07-2161-68a1-2eda-c1c16b26cf7c.png)

```sql
WHERE "node_field_data"."type" IN ('article', 'news', 'blog')
```

いい感じですね。

今回はOR検索をしましたが、もちろんAND検索もできます。「a,b,c」

例えば、カテゴリが「Drupalタグ」「PHPタグ」の両方を持っている記事一覧というようなシチュエーションで使えますね。

## 動的フィルタリング設定

今までは静的なフィルタリング設定と基本的な使い方を紹介しました。

本当の強みはこれからです。

### 自分の作成したコンテンツ一覧

よくある動的要素、ログインユーザーです。

Qiitaでもありますよね。
「自分の投稿した記事一覧」あれを作ります。

Contextual Filter 内の「投稿者」を選択します。

固定値で、「タイプ: ログインユーザーのユーザーID」とありますので設定してください。

![スクリーンショット 2024-06-16 1.15.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334980/7fd9a949-5a60-f536-164f-43e91edcd9bd.png)


クエリとプレビューを見てみましょう。

![スクリーンショット 2024-06-16 1.15.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334980/228e0981-5d8c-cf0a-fd9c-94ac045fa88a.png)

```sql
WHERE (node_field_data.uid = '1')
```

ちゃんとWHERE句が設定されていますね。
「自分の投稿した記事一覧」...。思ったより簡単ですよね。
`ユーザーID: 2`でログインしている場合は、`WHERE (node_field_data.uid = '2’)`となります。

### URLからArgumentを取得
次は、URLからArgumentを取得してみようと思います。

#### 1. PageDisplayの作成
PageDisplayを作成してください。Path設定が結構大事です。

![スクリーンショット 2024-06-16 1.22.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334980/9c4534f9-68c5-fb15-fee8-f279b46af739.png)

`「view/%bundle/%tag」`

なんとなくイメージつきますか？

`{サイトのURL/view/article/1}`
このURLにアクセスした際には、記事（article）かつ、タグ(Taxonomy:id)が1のものをリスト化します。

つまり、動的要素を2つ渡すことができるViewsを構築します。
動作を見てみたらしっくりきます。とりあえず設定をしてみましょう。

#### 2. Filterの設定
- コンテンツタイプ
- タグ

上記、２つのフィールドをフィルターに追加してください。
フィルター設定内で特別な設定はいりません。(デフォルトのまま)

順番によって、Argumentの受け取り方が変わりますので並び順が結構大事です。

![スクリーンショット 2024-06-16 2.28.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334980/eb4eddba-2c6e-e765-ab1e-67061b70a826.png)
この順番になっていたらOK。

#### 3. さらっとタイトルのオーバーライド
Viewsのタイトルを動的に変更できます。
以下の様に設定してみました。

![スクリーンショット 2024-06-16 1.46.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334980/0f3837eb-49ea-3bbb-fc86-fc48cc1ab22e.png)
`{{ arguments.type }}コンテンツタイプ / TermID: {{ arguments.field_tags_target_id }}` 

Twigが使えるようなので、カスタムフィルターやカスタム関数を実装すると幅が広がりますよね。

#### 4. 検証の条件を指定？
現状、URLに入ってきたタグのIDでしか絞り込みをしない設定になっていますがタグのバンドルを指定したい場合ありますよね？

例えば記事専用のタグだけを使いたい。管理用のタグは含みたくない。とか。
結構設定簡単です。

![スクリーンショット 2024-06-16 1.49.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334980/26f8c580-d461-1877-81e4-72d5e6caa499.png)

### 動作チェック!!
２つのArgumentをちゃんと受け取ってくれるか確認してみます。

#### `/view/article/1` の場合
![スクリーンショット 2024-06-16 2.36.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334980/c16ca25c-69e7-0dfe-c960-fac3765c240e.png)

#### `/view/article/2` の場合
![スクリーンショット 2024-06-16 2.36.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334980/8a7a9845-14f7-f3b4-51eb-95eb33cf8c43.png)

#### `/view/news/all` の場合
![スクリーンショット 2024-06-16 2.36.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334980/b3577aa8-f900-a895-314d-c8a2b348dccf.png)

いい感じに絞り込めてますね。

いきなり2つのArgumentを設定するやり方をしてみましたが、コンテンツタイプごとでも、タグごとでも絞り込みができているようです。

## まとめ
いかがでしょうか？

今回紹介できたのは、ほんの一部分...。
Contexual Filterはできることが多すぎます。

使いこなせば、HOOKやカスタムクエリの実装箇所をかなり吸収できそうですよね。

本記事では触れてませんが、EVAモジュールと組み合わせてContextの渡し方をより柔軟にしたり、CustomCacheTagsモジュールでArgument単位でのキャッシュタグ設定をしたりと、かなり幅を広げることが可能です。

次回は最終回です。[Tutorial 編](https://qiita.com/umekikazuya/items/520efa0cd8689c0f3d8b) !!
MBTIをテーマにViewsを作っていきます。ぜひ、いっしょに実践してみましょう。

お楽しみに。

## 参考
:::note info
SQLの基本的な知識があると更に理解が深まります。
SQLシリーズも執筆してますのでぜひ。
[【SQLマスターへの道】NULL値を制御「COALESCE」](https://qiita.com/umekikazuya/items/85b10b3dc63909bc43dd)
[【SQLマスターへの道】条件付きソート「CASE・WHEN」](https://qiita.com/umekikazuya/items/a0132b6ac5123002932e)
[【SQLマスターへの道】入社年度で学ぶ 「BETWEEN」](https://qiita.com/umekikazuya/items/61c16a36824c334e31e5)
:::