it-swarm.com.de

Fügen Sie dem benutzerdefinierten Inhaltsentitätstyp ein neues Feld hinzu

Ich habe einen benutzerdefinierten Inhaltsentitätstyp mit dem Namen Course erstellt. Bei der Installation meines Moduls hat Drupal automatisch das Tabellenschema für meine Entität erstellt, sodass alle in Course::baseFieldDefinitions() definierten Felder ihre Spalte in der Datenbanktabelle course, wie in der Anmerkung base_table meiner Klasse angegeben.

Jetzt möchte ich meiner Entität ein zusätzliches Feld hinzufügen. Ich habe die Methode Course::baseFieldDefinitions() bearbeitet, um mein neues Feld auf die gleiche Weise wie bei den vorherigen zu definieren. Das Problem ist, dass ich nicht weiß, wie ich die entsprechende Spalte in der Datenbank erstellen kann.

Der relevante Teil meiner Entität Course ist:

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

}

Ich habe versucht, den Konsolenbefehl Drupal] update:entities Zu verwenden, aber mein Datenbankschema wird nicht aktualisiert.

Wie kann ich das Feld place zu meiner Datenbanktabelle hinzufügen?

4
crbelaus

Nach der Installation müssen Sie das Schema selbst aktualisieren. Es gibt verschiedene Szenarien, einige sind einfacher zu handhaben als andere. Am komplexesten ist das Verschieben von Daten von einem Feldtyp in einen anderen, was bedeutet, dass Sie eine Datenmigration durchführen müssen.

Wie auch immer, Drupal Core hat die entityDefinitionUpdateManager(), auf die über \Drupal::entityDefinitionUpdateManager() zugegriffen werden kann. Dieser Manager kann viele Dinge tun, die Sie tun müssen, wenn Sie die Basisfelder von Inhaltsentitäten ändern.

Das Erstellen eines neuen Feldes ist ziemlich einfach und alles, was Sie brauchen, um Ihren eigenen Update-Hook zu erstellen:

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

Dadurch werden alle Aktualisierungen auf alle Entitäten angewendet. Dies kann im Allgemeinen für die meisten Dinge verwendet werden. Wenn jedoch Daten in Drupal vorhanden sind, wird eine Ausfallsicherheit ausgelöst, die eine Ausnahme auslöst, um sicherzustellen, dass die Daten nicht versehentlich durcheinander gebracht werden. Während der Beta versuchte das System auch, die Datenmigration zu handhaben, aber es funktionierte nicht gut, so dass entschieden wurde, dass dies etwas ist, was Modulbetreuer selbst tun sollten.

6
googletorp

Wie in Aktualisierungsfunktionen für Entitätsschema-Aktualisierungen schreiben, Automatisierung entfernt (erstellt im August 2015) beschrieben, beschreibt dies eine Änderung, die im 8.0.x-Zweig eingeführt wurde, wenn Sie das für ein verwendete Datenbankschema aktualisieren müssen Entität müssen Sie auch hook_update_N() mit Code implementieren, der dem folgenden ähnlich ist.
Da die Klasse, die die Entität implementiert, Course ist, gehe ich davon aus, dass der Name der Modulmaschine Kurs ist. Ändern Sie die Aktualisierungsnummer in die richtige für Ihr Modul.

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

Ich habe auch einen Tippfehler in Ihrem Code behoben: Anstelle von "weight", Sie schrieben "wegith".

Der Code, den ich zeige, dient zum Hinzufügen eines neuen Feldes. Der von mir verknüpfte Änderungsdatensatz zeigt auch den Code an, der verwendet werden soll, wenn vorhandene Felder zu Entitätsschlüsseln heraufgestuft werden oder wenn die Kardinalität eines Felds mit vorhandenen Daten von einfach zu mehrfach (oder von mehrfach zu einzeln) geändert wird.

Bevor Automatische Entitätsaktualisierungen können fehlschlagen, wenn vorhandener Inhalt vorhanden ist und das Schema der Site in einem unvorhersehbaren Zustand bleibt (eines der Probleme, die mit dem Änderungsdatensatz verknüpft sind) behoben wurde, musste update.php ein automatisiertes System beheben das Entitätsschema, das den Status des Entitätsschemas für Modulaktualisierungen nicht vorhersehbar gemacht hat.
Angesichts des Zweigs, in dem die automatischen Aktualisierungen entfernt wurden, würde ich sagen, dass praktisch alle Module Code verwenden müssen, der dem in dieser Antwort gezeigten ähnlich ist.

5
kiamlaluno

Ab Drupal 8.7.0 müssen Sie die Update-API für diese Aufgabe wie folgt verwenden:

Im modulename.install füge eine Funktion wie diese hinzu:

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

Dann renne drush updatedb oder gehen Sie im Statusbericht zu Datenbankaktualisierungen.

Siehe https://www.drupal.org/node/3034742 für ein tieferes Verständnis.

1
Rainer Feike

Sie sollten den Befehl mit drush drush updatedb --entity-updates ausführen

1
vizer03

Der Code für ein einzelnes Update ähnelt dem folgenden.

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