В Drupal 7 можно было получить физические имена таблиц базы данных, используя следующий код, это было довольно просто.
$field_definitions = field_info_fields();
foreach ($field_definitions как $field => $definition) {
$current_storage = $definition['storage']['details']['sql'][FIELD_LOAD_CURRENT];
$current_table = ключ($current_storage);
$revision_storage = $definition['storage']['details']['sql'][FIELD_LOAD_REVISION];
$revision_table = ключ($revision_storage);
}
В Drupal 9 API сущностей изменился к лучшему, и теперь существуют классы и сервисы для извлечения информации такого типа.Это все хорошо, я понимаю большинство концепций, связанных с этим, но я не могу на всю жизнь экстраполировать, как получить те же самые данные.
Моя цель - перебрать все мои типы сущностей, которые реализуют ContentEntityTypeInterface, получить их поля, а затем построить массив, который выглядит примерно так: у меня есть очень специализированный скрипт Drush, который я пытаюсь перенести с Drupal 7.
$ пример = [
'узел' => [
'поле_что-то' => [
'current' => 'some_table_name'
'revision' => 'some_table_name'
]
],
'заблокировать' => [
'поле_что-то' => [
'current' => 'some_table_name'
'revision' => 'some_table_name'
]
]
];
*Конечно, принимая во внимание, действительно ли поле может быть изменено.
Самостоятельно я определил, что по большей части имена таблиц в конечном итоге выглядят как $entityType . '__' . $поле['имя'] и $entityType . '_revision__' . $поле['имя'] но жесткое кодирование моего скрипта ломается, когда используются уникальные идентификаторы. Например, пользовательские блоки имеют имена таблиц, такие как block_content_r__7fe666c7a4. Мне нужно иметь возможность вытащить эти данные из своего рода «определения полевого хранилища».
Решение:
Согласно @Clive, решение состояло в том, чтобы получить класс хранения для каждого типа объекта, а затем использовать его для получения сопоставлений таблиц. Это прекрасно работает для небазовых полей, но если вам нужно базовое поле, решение будет другим. Вот что у меня получилось:
$поля = [];
foreach ($this->getContentEntityTypes() as $contentEntityType) {
$tableMapping = $this->entityTypeManager->getStorage($contentEntityType->id())->getTableMapping();
foreach ($this->entityFieldManager->getFieldStorageDefinitions($contentEntityType->id()) as $field) {
// Мы используем requireDedicatedTableStorage() для фильтрации базовых полей
если ($tableMapping->requiresDedicatedTableStorage($field)) {
$fieldInfo = [
'имя' => $field->getName(),
'тип' => $field->getType(),
'table' => $tableMapping->getDedicatedDataTableName($field)
];
если ($field->isRevisionable()) {
$fieldInfo['table_revision'] = $tableMapping->getDedicatedRevisionTableName($field);
}
$fields[$contentEntityType->id()][] = $fieldInfo;
}
}
}
вернуть $поля;
Я написал отдельный метод для получения своих объектов контента, который использовал приведенный выше код.
функция getContentEntityTypes() {
$contentEntityTypes = [];
$entity_type_definitions = $this->entityTypeManager->getDefinitions();
/* @var $definition EntityTypeInterface */
foreach ($entity_type_definitions как $entityType) {
if ($entityType instanceof ContentEntityTypeInterface && in_array(SqlEntityStorageInterface::class, class_implements($entityType->getStorageClass())))) {
$contentEntityTypes[] = $entityType;
}
}
вернуть $contentEntityTypes;
}