LoginSignup
3
3

More than 5 years have passed since last update.

Drupal8のViewsでタクソノミーの階層を辿る検索

Last updated at Posted at 2018-07-29

概要

Viewsの検索機能でタクソノミーを階層ごとにAjaxで呼び出せるようにする方法です
文字で説明するとよく分からないので画像貼り付けます

image.png

タグのような自由追加が可能なタクソノミーより、カテゴリーのようなサイトオーナー側が作成するタクソノミーを想定しています
基本的にはモジュールを入れればできるのですが、細かい調整が難しいので説明していきます

準備

必要なモジュール

インストール

CommandLine
composer require drupal/shs
drush en shs

基本設定の手順

タクソノミーを作成

ボキャブラリーを用意します
今回は新しく作成しますが、用いたいボキャブラリーがあればそのまま利用しても大丈夫です
image.png

階層化するタームを用意していきます
これも既に用意してあればそのまま利用して大丈夫です
image.png
野菜が食生活をよく表していますね

ノードの設定

ノードに作成したタクソノミのフィールドを用意します
今回は「記事」コンテンツタイプにフィールドを追加しています
image.png

参照タイプで作成したボキャブラリを指定します
image.png

フォームの管理でウィジェットを「Simple hierarchical select」を指定しておくと、フォームでも階層のAjaxで選択できるようになります
image.png

ウィジェットの右側の設定から「Force selection of deepest level」をチェックしてください
これにより、子要素を選択しないと保存できないようになります
image.png

Viewsを作成

Viewsを作成します
タクソノミを設定したタイプを指定し、ページを作成するにチェックします
image.png

今回は表示する内容は関係なく、検索できることが目的なので「フィルターの条件」以外はそのまま使用します
なので、好きなように設定してください
image.png

「フィルターの条件」に「タクソノミータームを含む」を追加します
image.png

作成したボキャブラリーと「Simple hierarchical select」を指定します
image.png

「このフィルターを訪問者へ表示し、変更できるようにする」にチェックして保存します
image.png

階層を辿った検索ができあがっています
image.png

問題点

検索機能はできましたが、ここで問題が生じます
まず、「果物 > バナナ」で最終階層まで検索すると普通に検索できるのが分かると思います
image.png

一つ上の階層、「果物」で検索するとコンテンツが見つかりません
image.png

上記の問題を解決するため、更に対応していきます

親要素の検索を可能にする

ノードの設定

ノードに親要素を保存するためのフィールドを追加します
先ほどと同じように作成したボキャブラリーを設定しましょう
image.png
image.png
image.png

フォームの設定でフォームから直接編集できないように設定しておきます
image.png

親要素を自動設定

簡単なモジュールを作成して、親要素を新しく作成したフィールドに自動作成します
よく分からない場合は、書いてある通りに作成すれば大丈夫です

モジュール名はcategory parentになっていますが、何でもいいです

CommandLine
mkdir -p modules/custom/category_parent
cd modules/custom/category_parent

vim category_parent.info.yml
vim category_parent.module
drush en category_parent

vimの部分はファイルへの書き込みなので、下のファイル名とコードを参照して入力(コピペなり)してください
iで入力モード、Escでモード離脱、Shift + Insertで貼り付け、:wqで保存して終了です

category_parent.info.yml
name: "Category Parent"
type: module
core: 8.x

$type, $field, $parentは使用するコンテンツタイプ、タクソノミーフィールド、親要素のタクソノミーフィールドのシステム名を指定してください

category_parent.module
<?php

/**
 * Implements hook_node_presave().
 */
function category_parent_node_presave(\Drupal\Core\Entity\EntityInterface $node) {
  $type = 'article';
  $field = 'field_category';
  $parent = 'field_category_parent';

  if ($node->getType() === $type) {
    if (!empty($node->{$field}->target_id)) {
      $term = \Drupal::entityTypeManager()
        ->getStorage('taxonomy_term')
        ->loadParents($node->{$field}->target_id);

      $node->{$parent}->entity = reset($term);
    }
  }
}

コンテンツに適用する

hook_node_presave()の設定はコンテンツを作成・編集する際に実行され、ノードを書き換えます
そのため、モジュールを有効化しただけでは、親タームの設定は行われていません

コンテンツページ(/admin/content)のアクションから「コンテンツの保存」で選択したアイテムに適用すれば、チェックした全てのコンテンツに実行できます
(このとき「コンテンツの削除」とかしないように注意しましょう)
image.png

検索の確認

作成した検索機能で親要素だけで検索してみましょう
親要素でも子要素でも検索できるようになっているのが確認できるかと思います
image.png

検索機能をブロック化したい

番外編で検索フォームをブロックにする方法です
作成したViewsの設定ページの「高度」「外部設置フォーム」の「外部設置フォームをブロックで提供」を「はい」に設定します
image.png

ブロックで検索フォームが利用できるようになります!
image.png

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3