web-dev-qa-db-fra.com

Ajouter un nouveau champ au type d'entité de contenu personnalisé

J'ai créé un type d'entité de contenu personnalisé appelé Course. Lorsque j'ai installé mon module, Drupal a automatiquement créé le schéma de table pour mon entité, donc tous les champs que j'ai définis dans Course::baseFieldDefinitions() avaient leur colonne dans la table de base de données course, comme spécifié dans l'annotation base_table de ma classe.

Maintenant, je veux ajouter un champ supplémentaire à mon entité. J'ai édité la méthode Course::baseFieldDefinitions() pour définir mon nouveau champ de la même manière que je l'ai fait avec les précédents. Le problème est que je ne sais pas comment créer la colonne appropriée dans la base de données.

La partie pertinente de mon Course entité est:

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

}

J'ai essayé d'utiliser la commande de console Drupal update:entities Mais elle ne met pas à jour mon schéma de base de données.

Comment puis-je ajouter le champ place à ma table de base de données?

4
crbelaus

Après l'installation, vous devez gérer vous-même la mise à jour du schéma. Il existe différents scénarios, certains sont plus faciles à gérer que d'autres. Le plus complexe consiste à déplacer des données d'un type de champ à un autre, ce qui signifie que vous devrez effectuer une migration des données.

Quoi qu'il en soit Drupal core a la entityDefinitionUpdateManager() à laquelle on accède par \Drupal::entityDefinitionUpdateManager(). Ce gestionnaire peut faire beaucoup de choses que vous devez faire lorsque vous changez les champs de base des entités de contenu.

La création d'un nouveau champ est assez facile, et tout ce dont vous avez besoin pour créer votre propre crochet de mise à jour:

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

Cela appliquera toutes les mises à jour à toutes les entités. Cela peut généralement être utilisé pour la plupart des choses, mais s'il y a des données dans Drupal a une sécurité intégrée qui lève une exception pour s'assurer qu'elle ne gâche pas accidentellement les données. Pendant la bêta, le système a tenté pour gérer également la migration des données, mais cela n'a pas bien fonctionné, il a donc été décidé que les développeurs de modules devraient le faire eux-mêmes.

6
googletorp

Comme décrit dans Écrire les fonctions de mise à jour pour les mises à jour du schéma d'entité, automatisation supprimée (créé en août 2015), qui décrit une modification introduite sur la branche 8.0.x, si vous devez mettre à jour le schéma de base de données utilisé pour un , vous devez également implémenter hook_update_N() avec un code similaire au suivant.
Puisque la classe implémentant l'entité est Course, je suppose que le nom de la machine du module est bien sûr . Remplacez le numéro de mise à jour par le numéro correct pour votre module.

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

J'ai également corrigé une faute de frappe dans votre code: au lieu de "weight", tu as écrit "wegith".

Le code que je montre est pour ajouter un nouveau champ. L'enregistrement de modification que j'ai lié montre également le code à utiliser lorsque les champs existants sont promus en clés d'entité, ou lorsque la cardinalité d'un champ avec des données existantes est changée de simple à multiple (ou de multiple à unique).

Avant les mises à jour automatiques d'entités peuvent échouer lorsqu'il existe du contenu existant, laissant le schéma du site dans un état imprévisible (l'un des problèmes liés à l'enregistrement des modifications) a été corrigé, update.php avait un système automatisé pour corriger le schéma d'entité, qui ne rendait pas l'état du schéma d'entité prévisible pour les mises à jour du module.
Étant donné la branche qui a supprimé les mises à jour automatiques, je dirais que pratiquement tous les modules doivent utiliser un code similaire à celui que je montre dans cette réponse.

5
kiamlaluno

À partir de Drupal 8.7.0 , vous devez utiliser l'API de mise à jour pour cette tâche, comme ceci:

Dans modulename.install ajoutez une fonction comme celle-ci:

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

Exécutez ensuite drush updatedb ou accédez à Mises à jour de la base de données dans le rapport d'état.

Voir https://www.drupal.org/node/3034742 pour une compréhension plus approfondie.

1
Rainer Feike

Vous devez exécuter la commande avec drush drush updatedb --entity-updates

1
vizer03

Le code d'une mise à jour individuelle est similaire au suivant.

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