Mise en jour du schema des entités Drupal 9
Les entités permettent de gérer les données dans une ou plusieurs tables, au cours du développement des sites web ou applications nous sommes généralement amener à créer des entités.
Ces derniers évoluent en function des besoins. Lorsque cela se produit tout au debut du développement ( sans information importante en BD), nous pouvons vider nos tables et utiliser le module Devel Entity Updates pour mettre à jour les schémas des table.
Mais si le besoin de mise à jour du schema des tables se fait ressentir plus tard, Drupal ne dispose pas pour le moment des API permettant de mettre cela à jour. Pour régler cela, nous devons écrire nos propres function de mise à jour.
Notre logique de mise à jour doit être implementer dans le hook hook_update_N. La logique de base est la suivante : Nous devons récupérer les données dans la table, vider cette dernière (généralement juste la colonne), appliquer la mise jour et réinjecter les données.
Cas pratique 1 : mise de la longueur (max_length) d'une colonne de type varchar.
nous disponsons d'un champs avec la configuration suivante :
...
$fields['name'] = BaseFieldDefinition::create('string')->setLabel(t('Name'))->setDescription(t('The name of the Site type datas entity.'))->setSettings([
'max_length' => 50,
'text_processing' => 0
])->setDefaultValue('')->setDisplayOptions('view', [
'label' => 'above',
'type' => 'string',
'weight' => -4
])->setDisplayOptions('form', [
'type' => 'string_textfield',
'weight' => -4
])->setDisplayConfigurable('form', TRUE)->setDisplayConfigurable('view', TRUE)->setRequired(TRUE)->setTranslatable(true);
...
Nous souhaitons faire passer le max_length à 250.
function __blockscontent_update_name_max_length($entity_type_id) {
/**
*
* @var \Drupal\Core\Entity\Sql\SqlContentEntityStorage $entityStorage
*/
$entityStorage = \Drupal::entityTypeManager()->getStorage($entity_type_id);
// Retrieve existing field data.
$database = \Drupal::database();
$table = $entity_type_id . '_field_data';
$names = $database->select($table, 'et')->fields('et', [
'id',
'langcode',
'name'
])->execute()->fetchAll(\PDO::FETCH_ASSOC);
// Remove data from the column.
$database->update($table)->fields([
'name' => NULL
])->execute();
//
// si les revisions sont activées.
if ($entityStorage->getRevisionTable()) {
$table_revision = $entity_type_id . "_field_revision";
$names_revision = $database->select($table_revision, 'et')->fields('et', [
'id',
'langcode',
'name'
])->execute()->fetchAll(\PDO::FETCH_ASSOC);
$database->update($table_revision)->fields([
'name' => NULL
])->execute();
}
// Remove old definition field.
$updateManager = \Drupal::entityDefinitionUpdateManager();
$storagedef = $updateManager->getFieldStorageDefinition('name', $entity_type_id);
$updateManager->uninstallFieldStorageDefinition($storagedef);
// Load new definition field in code.
/**
*
* @var \Drupal\Core\Entity\EntityFieldManager $fieldManager
*/
$fieldManager = \Drupal::service('entity_field.manager');
$fields = $fieldManager->getFieldStorageDefinitions($entity_type_id);
$updateManager->installFieldStorageDefinition('name', $entity_type_id, "gestion_tache", $fields['name']);
// Restore entity data in the new schema.
foreach ($names as $name) {
$database->update($table)->fields([
'name' => $name['name']
])->condition('id', $name['id'])->condition('langcode', $name['langcode'])->execute();
}
// restore revision
if ($entityStorage->getRevisionTable())
foreach ($names_revision as $name) {
$database->update($table_revision)->fields([
'name' => $name['name']
])->condition('id', $name['id'])->condition('langcode', $name['langcode'])->execute();
}
}
/**
* Update value max_length from 50 to 250.
*
* implement hook_update_8001
*
* @see https://www.drupal.org/node/2554097
*/
function blockscontent_update_8001() {
__blockscontent_update_name_max_length('blocks_contents');
}