フィールドタイプを変更するにはどうすればよいですか?


9

タイプがText(プレーン、ロング)であるfield_mapsを持つコンテンツタイプがあります。テキスト(プレーン)に変更する必要がありました。

したがって、次のSQLステートメントを実行しました。

ALTER TABLE node__field_maps MODIFY field_maps_value VARCHAR(200);

field_typeがに変更されたようですVARCHAR(200)が、まだ問題が1つあります。コンテンツタイプと管理フィールドのタブで、フィールドがText(plain、long)として表示されます。

テキスト(プレーン)に変更するにはどうすればよいですか?


データベースに本番データがありますか?古いフィールドを削除して、好きなようにインストールするのが最も簡単な方法だからです。
Eyal

1
@Hefiあなたは同様のQ に対する私の答えを試すことができます。あなたがそれをしている間、あなたは常にあなたのサイトを数秒/分のメンテナンスモードに置くことができます。最初にtest / devサーバーで予行演習を行ってください。
Sssweatなし16

1
このタスクを実行するには、更新フックを記述する必要があります。基本的には、データを変数にコピーし、フィールドを削除して新しいフィールドをインストールし、データを挿入する必要があります。(すべて同じ更新機能内)
Eyal

回答:


13

既存のデータを使用してフィールドタイプを別のフィールドタイプに変更するこの種の問題も発生しています。@Eyalが述べたように、更新フックを

  1. フィールドテーブルから変数にデータをエクスポートする
  2. すべてのバンドルのフィールドを削除する
  3. すべてのバンドルの新しいフィールドを追加する
  4. データをフィールドテーブルに復元する

これがコード例です

use \Drupal\field\Entity\FieldStorageConfig;
use \Drupal\field\Entity\FieldConfig;

/**
 * Change node__field_maps from string_long to string type.
 */
function mymodule_update_8XXX() {
  $database = \Drupal::database();
  $table = 'node__field_maps';
  $entity_type = 'node';
  $field_name = 'field_maps';

  $field_storage = FieldStorageConfig::loadByName($entity_type, $field_name);

  if (is_null($field_storage)) {
    return;
  }

  $rows = NULL;

  if ($database->schema()->tableExists($table)) {
    // The table data to restore after the update is completed.
    $rows = $database->select($table, 'n')
      ->fields('n')
      ->execute()
      ->fetchAll();
  }

  $new_fields = array();

  // Use existing field config for new field.
  foreach ($field_storage->getBundles() as $bundle => $label) {
    $field = FieldConfig::loadByName($entity_type, $bundle, $field_name);
    $new_field = $field->toArray();
    $new_field['field_type'] = 'string';
    $new_field['settings'] = array();

    $new_fields[] = $new_field;
  }

  // Deleting field storage which will also delete bundles(fields).
  $new_field_storage = $field_storage->toArray();
  $new_field_storage['type'] = 'string';
  $new_field_storage['settings'] = array(
    'max_length' => 255,
    'is_ascii' => FALSE,
    'case_sensitive' => FALSE,
  );

  $field_storage->delete();

  // Purge field data now to allow new field and field_storage with same name
  // to be created. You may need to increase batch size.
  field_purge_batch(10);

  // Create new field storage.
  $new_field_storage = FieldStorageConfig::create($new_field_storage);
  $new_field_storage->save();

  // Create new fields.
  foreach ($new_fields as $new_field) {
    $new_field = FieldConfig::create($new_field);
    $new_field->save();
  }

  // Restore existing data in the same table.
  if (!is_null($rows)) {
    foreach ($rows as $row) {
      $database->insert($table)
        ->fields((array) $row)
        ->execute();
    }
  }

}

注:このコードを実行する前に、常にDBとテストコードをバックアップしてください。

その他の考え 私の場合、構成もエクスポートしました。これは、フィールドのタイプと設定がfield_storage_config、field_config、entity_form_display、およびentity_view_display構成ファイルにも含まれていることを意味します。そのため、これらのファイルの構成設定も更新する必要があります。簡単な方法は次のとおりです。

  • あなたのウェブサイトを複製する
  • フィールドを削除し、フィールドUIで同じ名前のフィールドを再度追加する
  • 構成をエクスポートしてリポジトリで使用する
  • インポートによってデータが削除される可能性を回避するために、フィールドとストレージの構成UUIDが変更されていないことを確認してください(変更されている場合はUUIDを元に戻します)。
  • DBの更新後に構成をインポートし、キャッシュを再度クリアする

これは、https: //www.drupal.org/node/2816859の投稿で@druganに触発されたコードです


1
素晴らしいコード-ありがとう!! 私はこれを同様のフィールド変更のために機能させました。新しいフィールドはフォームの表示で無効になることに注意してください。最初は機能していないと思いましたが、その後は無効になっているだけだと気づきました。
wheelercreek

テーブルをコピーし、フィールドとテーブル値の名前を変更して、コンテンツをコピーしました。値が新しいフィールドに表示され、コンテンツをプレーンテキストから数値に移動しました。これで、番号(整数)に従って並べ替えを設定しました。2。よりもプレーンテキスト10に従って表示されます。これの解決策はあなたの助けが必要ですか?
Manmeet Khurana

更新フックは実際に機能しますが、いくつかの異なるフィールドでテストしましたが、構成のインポートでは構成が別のフィールドとして認識され、元のフィールドが削除されるため、構成の提案処理により、そのフィールドに保存されているすべてのデータが失われます。新しいものを追加する前の内容。これを回避するには、構成をエクスポートしたら、構成のuuidが変更されていないことを確認します(基本的には元のフィールドのuuidに戻します)。これにより、構成システムは同じフィールドであると想定し、更新します。この情報を含めるように回答を編集しました。
Dion S. Jensen

0

私は同様の問題に直面していました。説明したupdate_hookを実行した後も、ステータス概要ページに「エンティティとフィールドの定義が一致しません」というメッセージが表示されていました。Drupal 8.7で削除されたdrush entupが原因だったと思います。FieldStorageDefinitionを次のように手動で強制的に更新することで解決できました。

function my_module_update_8002() {
  $entity_definition_update_manager = \Drupal::entityDefinitionUpdateManager();
  $entity_type = '[my_entity_type]';
  $field_name = '[my_field_name]';
  $field_storage = FieldStorageConfig::loadByName($entity_type, $field_name);
  $entity_definition_update_manager->updateFieldStorageDefinition($field_storage);
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.