logo

パレット - カラフルに🎨

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

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

Scroll

9.10. Drupal Fields API。データベース内の Drupal フィールド。

01/10/2019, by mikhail

mysql

この記事では、Drupal のフィールドがどう動作するか、なぜ必要なのか、そしてフィールドが Drupal でのサイト開発をどう素早くするのに役立つかを理解します。

前の記事ですでにフィールドを扱いました:

7.5. bootstrap カラムでサービスブロックを組む

7.6. Drupal 用の Isotope ギャラリー

7.7. youtube 動画付きブロック Drupal

それでは、どう動作するか見ていきましょう。Article タイプのコンテンツフィールドの編集に移動し、新しい Link タイプのフィールドを追加しましょう:

/admin/structure/types/manage/article/fields

add field

新しい記事を作成すると、2 つの入力――URL とテキストリンク――が表示されます:

link

管理画面を通じて新しいフィールドを作成するたびに、データベースに 2 つのテーブルが作成されます:

{entity_type}__{field_name}
{entity_type}_revision__{field_name}

Drupal はリビジョンをサポートしているので、すべてのデータは少なくとも 1 回複製されます。というのも、唯一のリビジョンがあなたの記事の現在のリビジョンだからです。したがって、フィールドと Drupal Fields API 全体は、データベースの操作を簡素化するために必要です。管理画面を通じてフィールドを作成するだけで、drupal がすでにデータベースにテーブルを作成します。

MySQL テーブルの名前から、同じフィールドが 1 つのタイプのエンティティに使えることが分かるはずです。ですから例えば、すでに存在する Link フィールドを Basic Page タイプのコンテンツで使えます:

/admin/structure/types/manage/page/fields/add-field

add field

しかし、ブロックに Link フィールドを作成したい場合は、新しいフィールドを作成する必要があります。同じフィールドを異なるタイプの Entity で使うことはできません。Basic Block タイプ用の Link フィールドを作成しましょう:

/admin/structure/block/block-content/manage/basic/fields/add-field

ご覧のとおり、フィールドを作成する際、既存のフィールドから Link フィールドを選ぶ選択肢はありません。というのも、Block と Node は異なるタイプの Entity だからです。

そして、ノードの場合と同様に、ブロック用の Link フィールドのデータを保存する 2 つのテーブルができます:

tables and views

block_content_revision__field_link と block_content__field_link。

次に、drupal が異なるバンドルのノードに対して同じフィールドのデータをどう保存するかを理解しましょう。Article ノードタイプ用に Link フィールドを作成し、次にこのフィールドを Basic Page ノードタイプで再利用しました。便宜上、サイトの構成をフォルダーにアップロードしてファイルを見るのが最善ですが、adminer や phpmyadmin を通じて config テーブルで必要な構成を見つけることもできます:

select config

link という単語を含むすべての構成を検索すると:

SELECT * FROM `config` WHERE CONVERT(`name` USING utf8mb4) LIKE '%link%' LIMIT 50

私たちの field_link フィールドに関して、次の構成が見つかります:

field.field.block.block_content.basic.field_link
field.field.node.article.field_link
field.field.node.page.field_link
field.storage.block_content.field_link
field.storage.node.field_link

各 Entity タイプについて、各フィールドは独自の Field Storage 構成を作成します。この構成は、テーブル {entity_type}__{field_name}、{entity_type}_revision__{field_name} にデータをどう保存するかに応答します。私たちの場合、これらは block_content_field_link、block_content_revision_field_link、node__field_link、node_revision__field_link テーブルです。次に、Link モジュールがデータをどう保存するかを調べます。Link フィールドの Field Storage 構成を開いてみましょう:

uuid: dba847ef-f4d6-4462-a2ee-f642a007fca6
langcode: en
status: true
dependencies:
  module:
    - block_content
    - link
id: block_content.field_link
field_name: field_link
entity_type: block_content
type: link
settings: {  }
module: link
locked: false
cardinality: 1
translatable: true
indexes: {  }
persist_with_no_fields: false
custom_storage: false

Field Storage 構成に正確に何が保存されているかが明確になるように、これらの各行を見てみましょう。

uuid: dba847ef-f4d6-4462-a2ee-f642a007fca6

ここには、各 Config に固有の Config ID が保存されています。ローカルでフィールドを作成して構成をアップロードした場合、staging で手動でフィールドを作成する必要はありません。フィールドは自動的に作成されます。フィールドを削除してローカルで構成を削除すると、staging にインポートした後、すべてのデータも削除されます。したがって、staging でフィールドを作成した場合は、構成をアップロードして git に追加し、変更を無駄にしないようにしてください。

langcode: en

多言語サイトでは、異なる言語の異なるバージョンのノードに対して、フィールドのテーブルにすべての言語のすべてのデータが保存され、特定のデータがどの言語を使うかを示します:

select

私は同じ言語を使っているので、構成のデフォルト言語も同じです。

status: true

すべての構成エンティティに共通するのは、このエンティティが有効か無効かを示す status フィールドです。Field Storage 構成は drupal で作成された構成エンティティを使います。FieldStorageConfig クラスを参照してください。これは ConfigEntityBase から継承されています:

https://api.drupal.org/api/drupal/core!modules!field!src!Entity!

dependencies:
  module:
    - block_content
    - link

アドオンモジュールへの依存です。ブロックで Link フィールドを使ったので、必須の Block content モジュールがあります。

id: block_content.field_link

私たちの構成の一意な名前です。

field_name: field_link

作成したフィールドのマシン名は Drupal が使います。ですから、このマシン名は例えばノードオブジェクトにアクセスする際に使えます $node->field_link->uri。Entity フィールドをどう参照するかは、次の記事で詳しく理解します。

Entity_type: block_content

私たちの Field Storage 構成がどのタイプの Entity か

type: link

Drupal のフィールドタイプです。独自のタイプのフィールドを作成しますが、今は、このフィールドタイプ link が Link モジュールによって作成されることだけを知っておく必要があります。次のクラスを見られます

core/modules/link/src/Plugin/Field/FieldType/LinkItem.php

これが私たちの構成で使われています。

settings: { }

ここにはフィールドタイプの設定を保存します。今は空ですが、例えば body フィールドには、ティーザーを表示するかどうかの設定があります:

config/sync/field.field.block_content.basic.body.yml

settings:
display_summary: false

module: link

link フィールドタイプを持つモジュールです。今はモジュール名とフィールドタイプ link が同じですが、異なる場合もあります。例えば、1 つのモジュールで複数のタイプのフィールドを実装できます。DateTime モジュールでそうされているように:

core/modules/datetime/src/Plugin/Field/FieldType/DateTimeFieldItemList.php
core/modules/datetime/src/Plugin/Field/FieldType/DateTimeItem.php

locked: false

フィールドが編集可能かどうかを示します。これはフィールドの設定を意味します。少し前、例えば Commerce モジュールの Billing Information と Shipping Information フィールドはブロックされていました。というのも、配送と税計算を使う際にこのフィールドの存在が必須だったからです。

cardinality: 1

このフィールドに入力できる 1 つの Entity に対する値の数です。1 つの値を選びましたが、ここでは別の数、2、3、5 などかもしれません。無制限の数の値には cardinality: -1 が使われます。

translatable: true

このフィールドが他の言語に翻訳可能かどうか

indexes: { }

このフィールドでのより良い検索のための追加の SQL インデックスです。通常、データベースクエリの構成と最適化に必要です。

persist_with_no_fields: false

すべての Entity からフィールドが削除された場合に Field Storage を削除するかどうかを示します。例えば、Article と Basic Page からフィールドを削除しても、Field Storage は削除されません。

custom_storage: false

Custom storage は、フィールドデータを保存するための特別なテーブルを持ち、{entity_type}__{field_name} ではないことを意味します。このようなものは使いませんが、他のシステムとの統合には便利なことがあります。

それでは、link フィールドタイプのファイルを開いてみましょう:

core/modules/link/src/Plugin/Field/FieldType/LinkItem.php

そして、このフィールドがデータベースにどんなデータを保存するか見てみましょう。これは propertyDefinitions() メソッドで見られます:

public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
  $properties['uri'] = DataDefinition::create('uri')
    ->setLabel(t('URI'));

  $properties['title'] = DataDefinition::create('string')
    ->setLabel(t('Link text'));

  $properties['options'] = MapDataDefinition::create()
    ->setLabel(t('Options'));

  return $properties;
}

ご覧のとおり、URI、Title、Options のデータを保存します。node__field_link テーブルを開くと、同じフィールドが見られます:

select

これで Drupal の Fields API のトピックにたどり着きました。LinkItem クラスを持つ PHP ファイルの中で、モジュールを通じてフィールドタイプを作成します。これにより、Entity 用のフィールドを作成でき、次にそれを使ってデータを入力し、このデータをデータベースに保存できます。これがデータ入力のケースです。Fields API はまた、私たちのフィールドのデータ入力と出力のフォームも構成します。

Article と Basic Page コンテンツタイプにフィールドを作成した時点に戻りましょう。Node の Field Storage 用の構成ファイルは 1 つ field.storage.node.field_link.yml ですが、フィールドを作成する際、Entity の各バンドルにもう 1 つ構成ファイルを作成します。ですから例えば、今はフィールドに 3 つの構成ファイルがあります

field.field.node.article.field_link.yml
field.field.node.page.field_link.yml
field.field.block.block_content.basic.field_link.yml

これらの構成は、フィールド設定フォームのデータを保存します:

link

このようにして、異なるバンドルに対して異なる方法でフィールドのデータ入力フォームをカスタマイズできます。バンドル内の 1 つ 1 つのフィールド構成は Drupal では Field Instance と呼ばれるので、まず各バンドルで個別に Field Instance で使える Field Storage フィールドを作成します。Drupal 8 では、Drupal 7 とは異なり、Field Instance を扱う関数はもうなく、インスタンスを扱う機能は CRUD API に移行しました:

https://www.drupal.org/node/2054619

コードを通じてフィールドを扱う例は、公式ドキュメントで見られます:

https://www.drupal.org/node/2012896

私たちは、フィールドデータのデータベースへの保存に関する Fields API の部分だけを見ました。次のいくつかのレッスンでは、Fields API がデータ入力とフィールドデータ出力をどう扱うかを見て、また独自の本格的なフィールドタイプを作ります。