9.11. Drupal Entity API。カスタムエンティティタイプの作成。Drupal Console を使ったエンティティタイプの生成。
すでに Form API、Fields API を理解し、Drupal のデータがどのようにデータベースに入るかも分かっています。次に、すべての Drupal サイトの基盤、すなわち Entity API を見ていきましょう。
おそらく、フィールドはそれ自体で存在するのではなく、エンティティ――ノード、ブロック、タクソノミー用語、ビューなど――に「付加」されていることにお気づきでしょう。バンドルエンティティ、例えば素材タイプ、ブロックタイプ、タクソノミー辞書を作成できます。しかし、独自のバンドルを持つ新しいエンティティを作成する必要がある場合はどうでしょうか?その場合、新しいエンティティを作成するために Entity API が必要になります。
すべてのコードを github の drupalbook_product モジュールに追加しました。モジュールをダウンロードして、私のウェブサイトに追加できます:
https://github.com/levmyshkin/drupalbook8
新しいエンティティタイプを作成するのは Drupal Console を通じて行うのが最も簡単です。というのも、たった 1 つのコマンドを実行するだけで済むからです。
新しいタイプのエンティティを頻繁に作成する必要はありません。ほとんどの中小規模のプロジェクトでは、基盤として contrib モジュールを使います。例えば、オンラインストア用の Commerce です:
https://www.drupal.org/project/commerce
独自のプラグインモジュールを作成しようとしている場合は、おそらく新しいタイプのエンティティを作成する必要があるでしょう。また、Drupal モジュールの中から、必要な機能を持つ、すでに適したモジュールを見つけることもできます。それに、足りない機能を追加したり補足したりできます。
この記事では、Entity API を分析し、独自のタイプの Product エンティティを作成します。これは、小さなカスタムカタログやストアの基盤となります。それでもカスタムストアを作成すると決めた場合は、Commerce を使うことを強くお勧めします。あなたと顧客の膨大な時間を節約できるからです。
新しいタイプのエンティティを作成したいとき、なぜ別の Product 素材タイプを作成してカタログに使えないのか、という疑問が生じます。はい、価格や在庫による Views 出力とシンプルなフィルターを持つ小さな商品カタログには、これができます。しかし、商品数が数千になると、マネージャーはコンテンツページで目的の商品を探すのが不便になります。マネージャーは、ページ上で品番、カテゴリー、色、名前によるフィルターとすべての追加キットを付けたくなります。
/admin/content
それは冗長に見え、他のタイプの素材 News、Articles、Events、Pages の作業を妨げます。したがって、そのような状況では、独自の管理パネルと設定を持つ別のタイプの Product エンティティを作ります。
それでは、別のタイプの Product エンティティの作成を始めましょう。エンティティタイプを作成するコマンドを実行する前に、サイトのバックアップ、少なくともデータベースのバックアップを作成することを強くお勧めします。というのも、エンティティタイプを作成するプロセスは、一部、データベースに書き込まれる config の生成から成り、何かがうまくいかず config の一部がモジュール内のエンティティタイプファイルなしで書き込まれると、サイトが壊れるからです。まずバックアップを作成してください。
次に、新しいモジュールを作成します。これも Drupal Console を通じて作成できます:
drupal generate:module
https://hechoendrupal.gitbooks.io/drupal-console/en/commands/generate-module.html
$ vendor/bin/drupal generate:module
// Welcome to the Drupal module generator
Enter the new module name:
> Drupalbook Product
Enter the module machine name [drupalbook_product]:
>
Enter the module Path [modules/custom]:
>
Enter module description [My Awesome Module]:
> Products catalog
!>
Enter package name [Custom]:
>
Enter Drupal Core version [8.x]:
>
Do you want to generate a .module file? (yes/no) [yes]:
> no
Define module as feature (yes/no) [no]:
> no
Do you want to add a composer.json file to your module? (yes/no) [yes]:
> no
Would you like to add module dependencies? (yes/no) [no]:
> no
Do you want to generate a unit test class? (yes/no) [yes]:
> no
Do you want to generate a themeable template? (yes/no) [yes]:
> no
Do you want proceed with the operation? (yes/no) [yes]:
> yes
Generated or updated files
Generation path: /home/laptop/projects/drupalbook
1 - /modules/custom/drupalbook_product/drupalbook_product.info.yml
Generated lines: "5"
あるいは、単に drupalbook_product.info.yml ファイルを持つモジュールを作成します:
name: 'drupalbook_product'
type: module
description: 'Products catalog'
core: 8.x
package: 'Drupalbook'
これで、Product エンティティタイプを生成できます。
https://hechoendrupal.gitbooks.io/drupal-console/en/commands/generate-entity-content.html
$ drupal generate:entity:content
$ vendor/bin/drupal generate:entity:content
// Welcome to the Drupal Content Entity generator
Enter the module name [admin_toolbar]:
> drupalbook_product
Enter the class of your new content entity [DefaultEntity]:
> DrupalbookProductEntity
Enter the machine name of your new content entity [drupalbook_product_entity]:
>
Enter the label of your new content entity [Drupalbook product entity]:
> Product
Enter the base-path for the content entity routes [/admin/structure]:
>
Do you want this (content) entity to have bundles? (yes/no) [no]:
> yes
Is your entity translatable? (yes/no) [yes]:
> yes
Is your entity revisionable? (yes/no) [yes]:
> no
// generate:entity:config
Enter the base-path for the config entity routes [/admin/structure]:
>
Generated or updated files
Generation path: /home/laptop/projects/drupalbook
1 - modules/custom/drupalbook_product/drupalbook_product.permissions.yml
2 - modules/custom/drupalbook_product/drupalbook_product.links.menu.yml
3 - modules/custom/drupalbook_product/drupalbook_product.links.task.yml
4 - modules/custom/drupalbook_product/drupalbook_product.links.action.yml
5 - modules/custom/drupalbook_product/src/DrupalbookProductEntityAccessControlHandler.php
6 - modules/custom/drupalbook_product/src/DrupalbookProductEntityTranslationHandler.php
7 - modules/custom/drupalbook_product/src/Entity/DrupalbookProductEntityInterface.php
8 - modules/custom/drupalbook_product/src/Entity/DrupalbookProductEntity.php
9 - modules/custom/drupalbook_product/src/DrupalbookProductEntityHtmlRouteProvider.php
10 - modules/custom/drupalbook_product/src/Entity/DrupalbookProductEntityViewsData.php
11 - modules/custom/drupalbook_product/src/DrupalbookProductEntityListBuilder.php
12 - modules/custom/drupalbook_product/src/Form/DrupalbookProductEntitySettingsForm.php
13 - modules/custom/drupalbook_product/src/Form/DrupalbookProductEntityForm.php
14 - modules/custom/drupalbook_product/src/Form/DrupalbookProductEntityDeleteForm.php
15 - modules/custom/drupalbook_product/drupalbook_product_entity.page.inc
16 - modules/custom/drupalbook_product/templates/drupalbook_product_entity.html.twig
17 - modules/custom/drupalbook_product/templates//drupalbook-product-entity-content-add-list.html.twig
18 - modules/custom/drupalbook_product/drupalbook_product.module
19 - modules/custom/drupalbook_product/drupalbook_product.module
20 - modules/custom/drupalbook_product/drupalbook_product.module
21 - modules/custom/drupalbook_product/config/schema/drupalbook_product_entity_type.schema.yml
22 - modules/custom/drupalbook_product/drupalbook_product.links.menu.yml
23 - modules/custom/drupalbook_product/drupalbook_product.links.action.yml
24 - modules/custom/drupalbook_product/src/Entity/DrupalbookProductEntityTypeInterface.php
25 - modules/custom/drupalbook_product/src/Entity/DrupalbookProductEntityType.php
26 - modules/custom/drupalbook_product/src/DrupalbookProductEntityTypeHtmlRouteProvider.php
27 - modules/custom/drupalbook_product/src/Form/DrupalbookProductEntityTypeForm.php
28 - modules/custom/drupalbook_product/src/Form/DrupalbookProductEntityTypeDeleteForm.php
29 - modules/custom/drupalbook_product/src/DrupalbookProductEntityTypeListBuilder.php
Generated lines: "1060"
モジュールが生成されたので、それを有効にすると、新しいエンティティタイプがサイトに表示されます:

エンティティを生成するとき、Drupal Console はエンティティタイプがどうあるべきかを尋ねます。
Enter the class of your new content entity [DefaultEntity]:
私たちのエンティティ用の PHP クラスの名前です。名前の末尾に Entity を付けるのが最善です。
Enter the machine name of your new content entity [drupalbook_product_entity]:
クラスのマシン名は、クラス名に基づいて提案されます。Enter を押すと、提案された名前が使われます。
Enter the base-path for the content entity routes [/admin/structure]:
あなたのタイプのエンティティは、CRUD 操作用の独自のページを持ちます:

商品ページの表示はかなり原始的ですが、将来的に改善したり、Views を通じて作成したりできます:

新しいエンティティを作成するには、まず Product タイプのエンティティタイプのバンドルを作成する必要があります。私たちはバンドル可能なエンティティを選びました:
Do you want this (content) entity to have bundles? (yes/no):
したがって、新しいタイプの商品を作成します。これは、異なるフィールド Weight、Size、Color、その他の追加特性を作成するために必要になります。例えば、モニターには画面の対角線サイズがあり、靴には靴のサイズがあります。
新しい Product タイプ - Clothes を作成しましょう:

これで、新しいタイプの商品でフィールドをカスタマイズできます:

少なくとも価格フィールドは間違いなく必要です。
いくつか商品を作成して、データベースを見てみましょう。drupalbook_product_entity テーブルがあり、その中に商品の UUID が保存されています:

もう 1 つ drupalbook_product_entity_field_data テーブルもあり、その中に Properties が保存されています。これらはエンティティの特別なフィールドで、テーブルに直接保存されます。というのも、Name(エンティティラベル、例えばこれはノードの Title)などのこれらのフィールドは、リビジョンによって変わらないからです。

フィールドを追加すると、各フィールドに 2 つのテーブルが作成されます。というのも、リビジョンを使うことを選んだからです:
Is your entity revisionable? (yes/no) [yes]
これで、新しいタイプのエンティティを作成する方法が分かったと思います。次の記事では、カスタムカタログ/ストアの機能を拡張します。
すべてのコードを github の drupalbook_product モジュールに追加しました。モジュールをダウンロードして、あなたのウェブサイトに追加できます: