カスタムDrushコマンドでタクソノミータームを生成する

  •  
 
funada2020年7月31日 - 12:44 に投稿

タグ

カスタムDrushコマンドでタクソノミータームを生成する

・前々回の記事「Drushのカスタムコマンドを作成する」
・前回の記事「カスタムDrushコマンドでコンテンツを生成する」

今回はDrushコマンドによってタクソノミータームを作ってみます。
方法は前回の「カスタムDrushコマンドでコンテンツを生成する」とほとんど同じですが、タクソノミータームはコンテンツと異なり、「ターム同士で親子関係を作れる」という特徴があります。この設定方法についても説明します。

今回はモジュール名を「drush_create_taxonomy」とします。作成するファイルは下記の通り。

  • drush_create_taxonomy.info.yml
  • drush.services.yml
  • composer.json
  • src/Commands/CreateTaxonomy.php

それでは順に作成していきましょう。

① drush_create_taxonomy.info.yml

name: Drush Create Taxonomy
description: 'タクソノミータームを作成します.'
core: 8.x
type: module

② drush.services.yml

services:
  drush_create_taxonomy.commands:
    class: \Drupal\drush_create_taxonomy\Commands\CreateTaxonomy
    tags:
      - { name: drush.command }

③ composer.json

{
  "name": "drupal/drush_create_taxonomy",
  "type": "drupal-module",
  "autoload": {
    "psr-4": {
      "Drupal\\drush_create_taxonomy\\": "src/"
    }
  },
  "extra": {
    "drush": {
      "services": {
        "drush.services.yml": "^9"
      }
    }
  }
}

ここまでは前回までと同じです。

④ CreateTaxonomy.php

<?php

namespace Drupal\drush_create_taxonomy\Commands;

use Drush\Commands\DrushCommands;
use Drupal\taxonomy\Entity\Term;

class CreateTaxonomy extends DrushCommands {

  /**
   * @command create-taxonomy
   * @aliases crta
   */
  public function createTaxonomy() {

    // 作成するタームを定義
    $terms = [
      ['vid' => 'tags', 'name' => 'tag_1', 'parent' => NULL],
      ['vid' => 'tags', 'name' => 'tag_1-1', 'parent' => 'tag_1'],
      ['vid' => 'tags', 'name' => 'tag_1-1-1', 'parent' => 'tag_1-1'],
      ['vid' => 'tags', 'name' => 'tag_1-1-2', 'parent' => 'tag_1-1'],
      ['vid' => 'tags', 'name' => 'tag_1-2', 'parent' => 'tag_1'],
      ['vid' => 'tags', 'name' => 'tag_1-2-1', 'parent' => 'tag_1-2'],
      ['vid' => 'tags', 'name' => 'tag_1-2-2', 'parent' => 'tag_1-2'],
      ['vid' => 'tags', 'name' => 'tag_2', 'parent' => NULL],
      ['vid' => 'tags', 'name' => 'tag_2-1', 'parent' => 'tag_2'],
      ['vid' => 'tags', 'name' => 'tag_2-1-1', 'parent' => 'tag_2-1'],
      ['vid' => 'tags', 'name' => 'tag_2-1-2', 'parent' => 'tag_2-1'],
      ['vid' => 'tags', 'name' => 'tag_2-2', 'parent' => 'tag_2'],
      ['vid' => 'tags', 'name' => 'tag_2-2-1', 'parent' => 'tag_2-2'],
      ['vid' => 'tags', 'name' => 'tag_2-2-2', 'parent' => 'tag_2-2'],
    ];

    // 定義したタームを1つずつ作成
    foreach ($terms as $term) {
      // 親タームが指定されている場合
      if ($term['parent'] != NULL) {
        $term_obj = Term::create([
          'vid' => $term['vid'],
          'name' => $term['name'],
          // 親ターム名からタームオブジェクトを取得
          'parent' => reset(taxonomy_term_load_multiple_by_name($term['parent'])),
        ]);
      }
      // 親タームが指定されていない場合
      else {
        $term_obj = Term::create([
          'vid' => $term['vid'],
          'name' => $term['name'],
        ]);
      }
      // タームを保存
      $term_obj->save();
    }
  }

}

まず、"Drupal\taxonomy\Entity\Term"をuseします。

コメント部分の@command create-taxonomy@aliases crtaは、実行するためのコマンドとその短縮形をそれぞれ規定しています。

今回は複数のタームを作るため、作成する全てのタームの情報を$termsという変数に配列として入れておきます。
$termsはただの配列であり、Drupalのタームオブジェクトとは関係ありません。

次に、Term::create()に配列を渡してタームのオブジェクトを作成していきます。親タームが存在する場合とそうでない場合(=最上位タームとして作成する場合)によって処理を分けています。

この配列が含んでいる"tid"、"name"、"parent"という3つの要素について、それぞれ簡単に説明しておきます。

  • vid

    そのタームが属するボキャブラリーを指定します。今回はデフォルトで存在する"tags"というボキャブラリーを指定しています。

  • name

    ターム名です。ちなみに同じ名前のタームが複数あっても特に問題ありません。

  • parent

    親タームを指定します。注意点として、ターム名ではなく対象タームのエンティティを入れる必要があります。'parent'は必須ではなく、指定しなければ自動的に最上位のタームとして作成されます。

reset(taxonomy_term_load_multiple_by_name($term['parent']))という部分では、$term['parent']に入っている文字列を「その名前を持つタームのオブジェクト」に変換する処理を行っています。
taxonomy_term_load_multiple_by_name()はターム名からタームオブジェクトを取ってくる関数ですが、その返り値は配列型です。(該当するタームが1つだけとは限らないためだと思います。) そのため、型をオブジェクト単体に変換するためにreset()関数で囲んでいます。

最後に$term_obj->save()で作成したオブジェクトを保存します。

コマンドの実行

ではモジュールを有効化し、コマンドを実行してみます。

install

drush create-taxonomy

タームが作成されているか確認

terms

指定した通りの階層構造が作られています。

ボキャブラリーが不正でないかチェック

最後に、存在しないボキャブラリーを"vid"として指定していないかチェックする処理を追加してみます。
まず、"Drupal\taxonomy\Entity\Vocabulary"を追加でuseします。

namespace Drupal\drush_create_taxonomy\Commands;

use Drush\Commands\DrushCommands;
use Drupal\taxonomy\Entity\Term;
use Drupal\taxonomy\Entity\Vocabulary;

次に、foreach文の先頭に次のコードを追加します。

      // 存在しないボキャブラリーの場合はタームを作成しない.
      $vocabularies = Vocabulary::loadMultiple();
      $vocabulary_names = [];
      foreach ($vocabularies as $vocabulary) {
        $vocabulary_names[] = $vocabulary->id();
      }
      if (!in_array($term['parent'], $vocabulary_names)) {
        $this->output()->writeln('ボキャブラリー "' . $term["vid"] . '" が存在しません.');
        continue;
      }

Vocabulary::loadMultiple()という関数を使ってサイトに存在するボキャブラリーのリストを取得し、$term["vid"]の値がそのリストに含まれているかをチェックします。もし含まれていない場合、タームを生成する処理を飛ばしてループを強制的に1つ進めます。

$termsで定義した'vid'の値を全て適当な値に変更し、再度コマンドを実行してみましょう。

ボキャブラリー "hoge" が存在しません.
ボキャブラリー "hoge" が存在しません.
ボキャブラリー "hoge" が存在しません.
ボキャブラリー "hoge" が存在しません.
ボキャブラリー "hoge" が存在しません.
ボキャブラリー "hoge" が存在しません.
ボキャブラリー "hoge" が存在しません.
ボキャブラリー "hoge" が存在しません.
ボキャブラリー "hoge" が存在しません.
ボキャブラリー "hoge" が存在しません.
ボキャブラリー "hoge" が存在しません.
ボキャブラリー "hoge" が存在しません.
ボキャブラリー "hoge" が存在しません.
ボキャブラリー "hoge" が存在しません.

タームは作成されず、このようなメッセージが表示されます。

 

コメントを追加

プレーンテキスト

  • HTMLタグは利用できません。
  • 行と段落は自動的に折り返されます。
  • ウェブページのアドレスとメールアドレスは自動的にリンクに変換されます。
CAPTCHA
この質問はあなたが人間の訪問者であるかどうかをテストし、自動化されたスパム送信を防ぐためのものです。