Wie ändere ich einen Feldtyp?

9

Ich habe einen Inhaltstyp mit einer Feldkarte, deren Typ Text ist ( normal , lang) . Ich musste es in Text (normal) ändern .

Also habe ich diese SQL-Anweisung gemacht:

ALTER TABLE node__field_maps MODIFY field_maps_value VARCHAR(200);

Es scheint, dass field_type in geändert wurde VARCHAR(200), aber es gibt noch ein weiteres Problem: Auf den Registerkarten Inhaltstyp und Felder verwalten wird das Feld weiterhin als Text (normal, lang) angezeigt .

Wie ändere ich es in Text (normal) ?

Hefi
quelle
Haben Sie Produktionsdaten in der Datenbank? Denn der einfachste Weg ist, das alte Feld zu löschen und nach Belieben zu installieren.
Eyal
1
@Hefi Sie können meine Antwort auf ein ähnliches Q versuchen . Sie können Ihre Site dabei immer für einige Sekunden / Minuten in den Wartungsmodus versetzen. Führen Sie zuerst einen Probelauf auf einem Test- / Entwicklungsserver durch.
Kein Sssweat
1
Sie sollten einen Update-Hook schreiben, um diese Aufgabe auszuführen. Grundsätzlich müssen Sie die Daten in eine Variable kopieren, das Feld löschen, das neue Feld installieren und die Daten wieder einfügen. (Alle in der gleichen Update-Funktion)
Eyal

Antworten:

13

Ich habe auch diese Art von Problem, das den Feldtyp mit vorhandenen Daten von einem zum anderen ändert. Wie @Eyal bereits erwähnt hat, können wir einen Update-Hook an schreiben

  1. Exportieren Sie Daten aus einer Feldtabelle in eine Variable
  2. Entfernen Sie die Felder aller Bundles
  3. Fügen Sie neue Felder aller Bundles hinzu
  4. Daten in Feldtabelle wiederherstellen

Hier ist das Codebeispiel

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

}

HINWEIS: Sichern Sie immer die Datenbank und den Testcode, bevor Sie diesen Code ausführen

Andere Gedanken In meinem Fall haben wir auch Konfigurationen exportiert, was bedeutet, dass der Feldtyp und die Einstellungen auch in den Konfigurationsdateien field_storage_config, field_config, entity_form_display und entity_view_display enthalten sind. Daher müssen wir auch die Konfigurationseinstellungen in diesen Dateien aktualisieren. Ein einfacher Weg könnte sein:

  • Klonen Sie Ihre Website
  • Löschen Sie das Feld und fügen Sie ein Feld mit demselben Namen erneut in die Feldbenutzeroberfläche ein
  • export konfiguriert, um sie im Repo zu verwenden
  • Stellen Sie sicher, dass die Konfigurations-UUID für das Feld und den Speicher nicht geändert wurde (ändern Sie die UUID zurück, falls dies der Fall war), um zu vermeiden, dass beim Import möglicherweise Daten entfernt werden.
  • Import konfigurieren nach DB-Update und Cache wieder löschen

Dieser Code wurde von @drugan im Beitrag https://www.drupal.org/node/2816859 inspiriert

eric.chenchao
quelle
1
Toller Code - danke !! Ich habe dies für einen ähnlichen Feldwechsel arbeiten lassen. Beachten Sie, dass das neue Feld in der Formularanzeige deaktiviert wird. Ich habe zunächst nicht gedacht, dass es funktioniert, aber dann festgestellt, dass es nur deaktiviert wurde.
Wheelercreek
Ich habe den Inhalt kopiert, indem ich Tabelle kopiere und Feld und Tabellenwert umbenenne. Der Wert wird jetzt in den neuen Feldern angezeigt und ich habe den Inhalt vom Klartext zur Zahl verschoben. Jetzt habe ich die Sortierung nach Nummer (Ganzzahl) eingestellt. Es wird immer noch nach Klartext 10 als 2 angezeigt. Was ist die Lösung dafür? Benötigen Sie Ihre Hilfe?
Manmeet Khurana
Während der Update-Hook tatsächlich funktioniert, nachdem er in mehreren verschiedenen Feldern getestet wurde, führt die vorgeschlagene Behandlung von config dazu, dass Sie alle in diesem Feld gespeicherten Daten verlieren, da beim Konfigurationsimport die Konfigurationen als separate Felder angezeigt werden und das Original damit gelöscht wird Inhalt vor dem Hinzufügen des neuen. Um dies zu vermeiden, stellen Sie nach dem Exportieren der Konfiguration sicher, dass die UUID der Konfiguration NICHT geändert wird (ändern Sie sie im Grunde wieder in die UUID des ursprünglichen Felds). Auf diese Weise nimmt das Konfigurationssystem an, dass es sich um dasselbe Feld handelt, und aktualisieren Sie es einfach. Ich habe Ihre Antwort so bearbeitet, dass sie diese Informationen enthält.
Dion S. Jensen
0

Ich hatte ein ähnliches Problem. Nach dem Ausführen des beschriebenen update_hook wurde auf der Statusübersichtsseite immer noch die Meldung "Nicht übereinstimmende Entitäts- und / oder Felddefinitionen" angezeigt. Ich denke, es lag daran, dass Drush Entup in Drupal 8.7 entfernt wurde. Ich konnte dies lösen, indem ich ein Update von FieldStorageDefinition wie folgt manuell erzwang:

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);
}
MathiasW
quelle