web-dev-qa-db-ja.com

カスタムコンテンツエンティティタイプに新しいフィールドを追加する

Courseというカスタムコンテンツエンティティタイプを作成しました。モジュールをインストールすると、Drupalがエンティティのテーブルスキーマを自動的に作成したため、Course::baseFieldDefinitions()で定義したすべてのフィールドにデータベーステーブルcourse、私のクラスの_base_table_アノテーションで指定されています。

次に、エンティティにフィールドを追加します。以前のフィールドと同じ方法で、Course::baseFieldDefinitions()メソッドを編集して新しいフィールドを定義しました。問題は、データベースに適切な列を作成する方法がわからないことです。

私のCourseエンティティの関連部分は次のとおりです。

_class Course extends ContentEntityBase implements CourseInterface {

  public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
    $fields = parent::baseFieldDefinitions($entity_type);

    $fields['user_id'] = BaseFieldDefinition::create('entity_reference');
      // Settings and constraints for this field

    $fields['name'] = BaseFieldDefinition::create('string');
      // Settings and constraints for this field

    $fields['price'] = BaseFieldDefinition::create("float");
      // Settings and constraints for this field

    $fields['status'] = BaseFieldDefinition::create('boolean');
      // Settings and constraints for this field

    $fields['created'] = BaseFieldDefinition::create('created');
      // Settings and constraints for this field

    $fields['changed'] = BaseFieldDefinition::create('changed');
      // Settings and constraints for this field

    // New field being added
    $fiels["place"] = BaseFieldDefinition::create("string")
      ->setLabel(t("Place"))
      ->setDescription(t("The place of the course"))
      ->setSettings(["max_length" => 255, "text_processing" => 0])
      ->setDefaultValue("")
      ->setDisplayOptions("view", ["label" => "above", "type" => "string", "wegith" => -3])
      ->setDisplayOptions("form", ["type" => "string_textfield", "wegith" => -3]);

    return $fields;
  }

}
_

Drupalコンソールコマンド_update:entities_を使用してみましたが、データベーススキーマが更新されていません。

placeフィールドをデータベーステーブルに追加するにはどうすればよいですか?

4
crbelaus

インストール後、スキーマの更新を自分で処理する必要があります。いくつかの異なるシナリオがあり、いくつかは他よりも扱いやすいです。最も複雑なのは、あるフィールドタイプから別のフィールドタイプにデータを移動することです。つまり、データの移行を行う必要があります。

とにかくDrupalコアにはentityDefinitionUpdateManager()があり、\Drupal::entityDefinitionUpdateManager()を使用してアクセスできます。このマネージャーは、変更したときに必要な多くのことを実行できますコンテンツエンティティの基本フィールド。

新しいフィールドの作成は非常に簡単で、独自の更新フックを作成するために必要なものはすべて次のとおりです。

function hook_update_8xxx() {
  \Drupal::entityDefinitionUpdateManager()->applyUpdates();
}

これにより、すべてのエンティティにすべての更新が適用されます。これは一般的にほとんどの場合に使用できますが、Drupalにデータがある場合、誤ってデータを混乱させないように例外をスローするフェイルセーフがあります。ベータ版の間にシステムはデータの移行も処理しますが、うまく機能しなかったため、これはモジュールのメンテナーが自分で行うべきことであると判断されました。

6
googletorp

エンティティスキーマの更新のための更新関数の書き込み、オートメーションの削除 (2015年8月に作成)で説明されています。これは、8.0.xブランチで導入された変更を説明します。エンティティ、次のようなコードでhook_update_N()も実装する必要があります。
エンティティを実装するクラスはCourseであるため、モジュールマシン名はcourseと想定します。更新番号をモジュールの正しい番号に変更します。

use Drupal\Core\StringTranslation\TranslatableMarkup;

function course_update_8110() {
  $storage_definition = BaseFieldDefinition::create("string")
    ->setLabel(new TranslatableMarkup("Place"))
    ->setDescription(new TranslatableMarkup("The place of the course"))
    ->setSettings(["max_length" => 255, "text_processing" => 0])
    ->setDefaultValue("")
    ->setDisplayOptions("view", ["label" => "above", "type" => "string", "weigth" => -3])
    ->setDisplayOptions("form", ["type" => "string_textfield", "weigth" => -3]);

  \Drupal::entityDefinitionUpdateManager()
    ->installFieldStorageDefinition('place', 'course', 'course', $storage_definition);
} 

また、コードのタイプミスを修正しました。"weight"の代わりに、"wegith"と書きました。

私が表示しているコードは、新しいフィールドを追加するためのものです。私がリンクした変更レコードは、既存のフィールドがエンティティキーにプロモートされたとき、または既存のデータを持つフィールドのカーディナリティが単一から複数(または複数から単一)に変更されたときに使用するコードも示しています。

以前は 既存のコンテンツがあるとエンティティの自動更新が失敗し、サイトのスキーマが予測不可能な状態のままになる (変更レコードからリンクされた問題の1つ)が修正され、update.phpは修正する自動システムを備えていましたエンティティスキーマ。モジュールアップデートでエンティティスキーマの状態を予測可能にできませんでした。
自動更新を削除したブランチを考えると、実質的にすべてのモジュールは、この回答で示したものと同様のコードを使用する必要があると言えます。

5
kiamlaluno

Drupal 8.7.0以降では、そのタスクに次のようにUpdate APIを使用する必要があります。

modulename.installに、次のような関数を追加します。

function modulename_update_8001() {
  $field_storage_definition = BaseFieldDefinition::create('timestamp')
    ->setLabel(t('Start'))
    ->setDescription(t('The first day'))
    ->setRevisionable(FALSE);

  \Drupal::entityDefinitionUpdateManager()
    ->installFieldStorageDefinition('start', $entity_type_id, $entity_type_id, $field_storage_definition);
}

次に、drush updatedbを実行するか、ステータスレポートの[データベースの更新]に移動します。

より深い理解については https://www.drupal.org/node/3034742 を参照してください。

1
Rainer Feike

Drush drush updatedb --entity-updatesを使用してコマンドを実行する必要があります

1
vizer03

個々の更新のコードは次のようになります。

function my_module_update_8400() {
  $entity_manager = \Drupal::entityManager();
  $reserved = $entity_manager->getFieldStorageDefinitions('table_name')['column_name'];
  $entity_manager->onFieldStorageDefinitionCreate($reserved);
}
0
user3127648