web-dev-qa-db-fra.com

Comment changer un type de champ?

J'ai un type de contenu avec un field_maps dont le type est Text (plain, long). Je devais le changer en Text (plain).

J'ai donc fait cette instruction SQL:

ALTER TABLE node__field_maps MODIFY field_maps_value VARCHAR(200);

Il semble que field_type est devenu VARCHAR(200), mais il y a encore un problème: sur les onglets de type de contenu et de gestion des champs, le champ est toujours affiché sous la forme Texte (simple, long).

Comment le changer en Text (plain)?

8
Hefi

J'ai également ce type de problème qui change le type de champ de l'un à l'autre avec les données existantes. Donc, comme @Eyal l'a mentionné, nous pouvons écrire un crochet de mise à jour pour

  1. exporter des données d'une table de champs vers une variable
  2. supprimer les champs de tous les lots
  3. ajouter de nouveaux champs de tous les bundles
  4. restaurer les données dans la table des champs

Voici l'exemple de code

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();
    }
  }

}

REMARQUE: Sauvegardez toujours la base de données et testez le code avant d'exécuter ce code

Autres réflexions Dans mon cas, nous avons également exporté des configurations, ce qui signifie que le type de champ et les paramètres sont également inclus dans field_storage_config, field_config, entity_form_display et entity_view_display fichiers de configuration . Nous devons donc également mettre à jour les paramètres de configuration dans ces fichiers. Une façon simple pourrait être:

  • cloner votre site web
  • supprimer le champ et ajouter à nouveau un champ portant le même nom dans l'interface utilisateur du champ
  • exporter des configurations pour les utiliser dans le repo
  • assurez-vous que l'uuid de configuration pour le champ et le stockage n'a pas été changé (changez l'uuid si c'est le cas) pour éviter que l'importation ne supprime potentiellement les données.
  • importer la configuration après la mise à jour de la base de données et vider à nouveau le cache

Ce code est inspiré de @drugan dans la publication https://www.drupal.org/node/2816859

12
eric.chenchao