logo

パレット - カラフルに🎨

Palette — ビジュアルページビルダー、デザインの専門知識は不要です。

ライブデモ パレットをダウンロード

Scroll
09/05/2020, by maria

Drupal 8のエンティティシステム

エンティティはメソッドを持つ型付きクラスです

Generic methods

$entity->id()

Entity type specific methods $node->getTitle()

 

Background

Entity SystemはDrupal 7の開発サイクルの終盤に、基本的なエンティティ読み込み標準とともに導入されました。追加されたentity.moduleはAPIをさらに拡張し、エンティティの保存・削除のサポートや、その他多くの改善を追加しました。

これらの改善のほとんどは現在Drupal 8に含まれています。エンティティの検証は独自のAPIで実行されるようになりました(たとえば、フォームではなくRESTで保存されたエンティティを検証できます)。

2つのバリエーション

コアのエンティティタイプには2つのバリエーションがあります。

設定エンティティ
Configuration Systemが使用されます。翻訳をサポートし、インストール用のカスタムデフォルト設定を提供できます。設定エンティティは共有の設定データベーステーブルに行として保存されます。

コンテンツエンティティ
カスタムフィールドと基本フィールドで構成され、リビジョンを持つことができ、翻訳をサポートします。コンテンツエンティティはカスタムデータベーステーブルに行として保存されます。テーブル名はエンティティの「id」と同じで、列はエンティティの「baseFieldDefinitions」メソッドで定義されます。

バンドル

バンドルはエンティティタイプの異なるバリエーションです。たとえば、ノードエンティティタイプの場合、バンドルは「記事」や「ページ」などのさまざまなノードタイプです。

通常、バンドルは設定エンティティで表されますが、contribモジュールには他のモデルもあります。たとえば、ノードの例では「article」ノードタイプ自体が設定エンティティです。設定には、設定やフィールドなど、コンテンツエンティティタイプ間の違いが保存されます。バンドル付きの新しいエンティティタイプを作成するとき、コンテンツの詳細と操作を管理するコンテンツエンティティと、コンテンツエンティティタイプ間の違いを処理する設定エンティティの両方を作成します。

アノテーション

新しいエンティティタイプを作成するときは、コアに組み込まれたアノテーションシステムを使用する必要があります。アノテーションはクラス上に置かれるdocblockコメントのように見えますが、Drupalコアによって解析・キャッシュされます。多くの点で、アノテーションはDrupal 7で使用されていたいくつかの古いスタイルに取って代わります。

アノテーションパーサー

アノテーションは、実行時にアノテーションエンジンによって読み取られ、解析されます。Drupal 8はDoctrineアノテーションパーサーを使用して、PHPが使用できるオブジェクトに変換します。

構文。 アノテーション構文は@ClassName()で囲まれ、主にkey/value pairsで構成され、中括弧を使用した配列を含めることができます。トップレベルのキーは引用符で囲んではいけませんが、配列キーは囲む必要があります。各key/value pairsは別々の行に置く必要があり、その行はコンマで終わる必要があります。特定の関数は値に対して実行できます。特に@Translation()関数です。

アノテーション構文の動作しない例:

/**
 * @ContentEntityType(
 *   id = "my_entity_type_id",
 *   label = @Translation("My entity type label"),
 *   example_pair = "this_examples_value",
 *   example_array = {
 *     "array_key" = "array_value",
 *     "some_other_key" = "some_other_value",
 *   },
 * )
 */

一般的なトップレベルのアノテーション

Key = "Example Value" 説明 Entityバリアント
id = "node",

エンティティタイプのマシン名。

Content & Config
label = @Translation("Node"),

エンティティタイプの読みやすい名前。

Content & Config
admin_permission = "administer nodes",

管理アクセスがエンティティタイプを設定・管理できるようにする権限。エンティティが「access」ハンドラを定義していない場合に必要です。

Content & Config
bundle_label = @Translation("Content type"),

バンドルエンティティタイプのオプションの読みやすい名前。

Content
bundle_entity_type = "node_type",

バンドル付きコンテンツエンティティを作成する場合、この値は設定エンティティの「id」である必要があります。この場合、「node_type」は設定エンティティです。

Content
base_table = "node",

エンティティタイプのデータベーステーブル名。

Content
fieldable = TRUE,

(boolean) このエンティティタイプをフィールドUIで拡張できるかどうか。

Content
field_ui_base_route = "entity.node_type.edit_form", エンティティのフィールドUIが結び付けられているルートの名前。 Content

 

Handlers

ハンドラはエンティティのアノテーションで配列として定義されます。これらは、実行の特定の部分を他のPHPクラスにマッピングすることでエンティティをサポートします。これらのクラスは、割り当てられたエンティティ実行部分を「処理」します。

ストレージ - エンティティの読み込み、保存、削除を処理します。デフォルトでは、コンテンツエンティティはDrupal\Core\Entity\Sql\SqlContentEntityStorageを使用し、設定エンティティはDrupal\Core\Config\Entity\ConfigEntityStorageを使用します。エンティティの標準ストレージメソッドを拡張するために、ストレージハンドラを定義できます。たとえば、エンティティのリビジョンIDを収集したり、エンティティが持つ翻訳の数を判別したりする追加メソッドを提供したい場合などです。
例:"storage" = "Drupal\node\NodeStorage",

フォーム - エンティティハンドラのアノテーションには複数のフォームハンドラがあり、エンティティの追加・編集・削除フォームを他のPHPクラスにマッピングします。
例:

"form" = {
  "add" = "Drupal\block\BlockForm",
  "edit" = "Drupal\block\BlockForm",
  "delete" = "Drupal\block\Form\BlockDeleteForm",
}

さらに、「add」フォームと「edit」フォームを個別に定義する代わりに、「default」フォームを定義して処理できます。「delete」フォームは、他のフォームとは別のクラスで処理されることがほぼ常です。これは、削除フォームが通常「確認フォーム」であり、ユーザーがエンティティを削除するかどうかを確認するだけだからです。

View builder - このハンドラは、エンドユーザーがエンティティを表示するときの出力を処理するクラスを提供します。たとえば、Drupal 8サイトでノードを訪れると、エンティティの出力はNodeViewBuilderクラスによって処理されます。
例:"view_builder" = "Drupal\node\NodeViewBuilder",

List builder - リストビルダークラスは、管理目的でエンティティのリストを処理します。このクラスは、エンティティの管理ページを訪れたときのヘッダー、行、操作の内容を定義します。たとえば、Drupalサイトの/admin/content URIを訪れると、テーブルの内容はNodeエンティティのリストビルダークラスによって提供されます。
例:"list_builder" = "Drupal\node\NodeListBuilder",

Route provider - オプションのハンドラで、実装されるとエンティティを管理するためのルートを生成します。このハンドラを実装すると、モジュールのrouting.ymlファイルで定義されたentityパスの必要性を置き換えることができます。route_providerは、エンティティに定義されたリンクと組み合わせて機能することに注意してください(下の「リンク」セクションの例を参照)。route_providerアノテーションは配列です。
例:

"route_provider" = {
  "html" = "Drupal\Core\Entity\Routing\AdminHtmlRouteProvider",
}

Access - アクセスハンドラは、エンティティの権限を動的にチェックするために使用できます。これは、EntityAccessControlHandlerInterfaceを実装するクラスへのマッピングです。コアはこのインターフェースの実装としてEntityAccessControlHandlerを提供しますが、エンティティを確実に制御するには、このクラスを独自のクラスで拡張したくなるでしょう。
例:"access" = "NodeAccessControlHandler",

Views data - views_dataハンドラは、エンティティが提供するカスタムデータでViewsモジュールを拡張できるようにします。これは、エンティティのbaseFieldDefinitionsをビューのフィールドとして追加したり、エンティティのリレーションシップでテーブルを結合したり、ビューに関連するデータの変更を行ったりするためのものです。
例:"views_data" = "Drupal\node\NodeViewsData",

Storage schema - storage_schemaハンドラは、エンティティのデータベースストレージ設定をさらに変更するために実装できます。たとえば、追加のテーブルインデックスを追加する場合などです。
例:"storage_schema" = "Drupal\node\NodeStorageSchema",

Translation. 翻訳ハンドラは、エンティティのフォームが翻訳と対話する方法を変更するために使用できます。
例:"translation" = "Drupal\node\NodeTranslationHandler",

完全なhandlersの例:
Drupalコアは「そのまま」使用できるハンドラを提供しますが、多くの場合、エンティティをより細かく制御・カスタマイズするために、これらのクラスを独自のクラスで拡張したくなるでしょう。この例では、拡張できるコアクラスを使用した、より完全なハンドラアノテーションを示しています。

handlers = {
  "view_builder" = "Drupal\Core\Entity\EntityViewBuilder",
  "list_builder" = "Drupal\Core\Entity\EntityListBuilder",
  "access" = "Drupal\Core\Entity\EntityAccessControlHandler",
  "views_data" = "Drupal\views\EntityViewsData",
  "storage" = "Drupal\Core\Entity\Sql\SqlContentEntityStorage",
  "storage_schema" = "Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema",
  "translation" = "Drupal\content_translation\ContentTranslationHandler",
  "form" = {
    "default" = "Drupal\Core\Entity\ContentEntityForm",
    "add" = "Drupal\Core\Entity\ContentEntityForm",
    "edit" = "Drupal\Core\Entity\ContentEntityForm",
    "delete" = "Drupal\Core\Entity\ContentEntityDeleteForm",
  },
  "route_provider" = {
    "html" = "Drupal\Core\Entity\Routing\AdminHtmlRouteProvider",
  },
},

リンク

リンクはエンティティのアノテーションで配列構文を使用して定義されます。リンクには特定のキーセットがあり、その値はエンティティタイプまたはそのタイプの個々のエンティティを管理できるURIです。これらのエンティティは、コンテンツと設定エンティティの両方で定義できます。

例:

id = "node",
handlers = {
  "route_provider" = {
    "html" = "Drupal\Core\Entity\Routing\AdminHtmlRouteProvider"
  }
},
links = {
  "canonical" = "/node/{node}",
  "add-page" = "/node/add",
  "add-form" = "/node/add/{node_type}",
  "edit-form" = "/node/{node}/edit",
  "delete-form" = "/node/{node}/delete",
  "collection" = "/admin/content",
},

これはNodeモジュールから逐語的に引用したものではなく、単なる例であることに注意してください。

これらのリンクを作成しても、これらのURIのルートは自動的に作成されません。これらのリンクを利用できるようにするには、モジュールに独自のrouting.ymlファイルを実装するか、エンティティのアノテーションでroute_providerハンドラを使用する必要があります。

リンクとルートプロバイダー

上記のリンクは「route_provider」と連携して、次の名前付きルートをDrupalで利用できるようにします。

リンクキー ルート名 ルートURIの例 説明
canonical entity.node.canonical /node/1 特定のノードを表示
add-page entity.node.add_page /node/add 追加するノードを選択
add-form entity.node.add_form /node/add/article ノードを追加(特定のバンドル)
edit-form entity.node.edit_form /node/1/edit 特定のノードのフォームを編集
delete-form entity.node.delete_form /node/1/delete 特定のノードのフォームを削除
collection entity.node.collection /admin/content すべてのノードをリストで表示

 

リンクの使用
これらのリンクは、エンティティのtoUrl()メソッドでアクセスできます:

$view_url_object = $entity->toUrl();  // Default is 'canonical'
$edit_url_string = $entity->toUrl('edit-form')->toString();

リンク: