Обновление схемы BaseFieldDefinition поля сущности в Drupal
Иногда при работе с сущностями Drupal возникает необходимость обновить структуру кастомного поля, которое состоит из нескольких колонок. Делается это следующим образом:
use Drupal\Core\Field\BaseFieldDefinition;
function site_commerce_order_update_8101($sandbox) {
// Менеджер обновлений сущностей.
$definition_update_manager = \Drupal::entityDefinitionUpdateManager();
// Менеджер для работы с базой данных.
$database = \Drupal::database();
// Получаем объект сущности, в которую вносим изменения.
$entity_type_manager = \Drupal::entityTypeManager();
$bundle_of = 'site_commerce_order';
$bundle_definition = $entity_type_manager->getDefinition($bundle_of);
// Получаем идентификатор ключевого поля сущности.
$id_key = $bundle_definition->getKey('id');
// Определяем имеет ли сущность отдельную таблицу для хранения данных.
// Если сущность не поддерживает переводы, то используется базовая таблица.
$storage = $entity_type_manager->getStorage($bundle_of);
$table_name = $storage->getDataTable() ?: $storage->getBaseTable();
// Сохраняем текущие значения поля из таблицы определения сущности.
$current_values = $database->select($table_name, 'n')
->fields('n', [
'delivery_address__latitude',
'delivery_address__longitude',
'delivery_address__country',
'delivery_address__region',
'delivery_address__postcode',
])
->execute()
->fetchAllAssoc($id_key, PDO::FETCH_ASSOC);
// Удаляем значения из таблицы определения сущности.
$database->update($table_name)
->fields([
'delivery_address__latitude' => NULL,
'delivery_address__longitude' => NULL,
'delivery_address__country' => NULL,
'delivery_address__region' => NULL,
'delivery_address__postcode' => NULL,
])
->execute();
// Получаем новое определение поля.
$new_field_definition = BaseFieldDefinition::create('delivery_address')
->setLabel(t('Delivery address'))
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);
// Удаляем текущее поле.
$field_storage_definition = $definition_update_manager->getFieldStorageDefinition('delivery_address', $bundle_of);
$definition_update_manager->uninstallFieldStorageDefinition($field_storage_definition);
// Устанавливаем новое определение поля.
$definition_update_manager->installFieldStorageDefinition('delivery_address', $bundle_of, $bundle_of, $new_field_definition);
// Восстанавливаем значения в поля таблицы определения сущности.
foreach ($current_values as $id => $value) {
$database->update($table_name)
->fields([
'delivery_address__latitude' => $value['delivery_address__latitude'],
'delivery_address__longitude' => $value['delivery_address__longitude'],
'delivery_address__country' => $value['delivery_address__country'],
'delivery_address__region' => $value['delivery_address__region'],
'delivery_address__postcode' => $value['delivery_address__postcode'],
])
->condition($id_key, $id)
->execute();
}
}