ใน 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
ตัวอย่าง $ = [
'โหนด' => [
'field_something' => [
'ปัจจุบัน' => 'some_table_name'
'แก้ไข' => 'some_table_name'
]
]
'บล็อก' => [
'field_something' => [
'ปัจจุบัน' => 'some_table_name'
'แก้ไข' => 'some_table_name'
]
]
];
*โดยคำนึงถึงว่าฟิลด์นั้นสามารถแก้ไขได้จริงตั้งแต่แรกหรือไม่
ด้วยตัวฉันเอง ฉันตัดสินใจเองว่าชื่อตารางส่วนใหญ่จะเป็นแบบเดียวกัน $entityType . '__' . $field['ชื่อ'] และ $entityType . '_revision__' . $field['ชื่อ'] แต่การฮาร์ดโค้ดสคริปต์ของฉันจะพังลงเมื่อมีการใช้รหัสเฉพาะ ตัวอย่างเช่น บล็อกแบบกำหนดเองจะมีชื่อตารางเช่น block_content_r__7fe666c7a4. ฉันต้องสามารถดึงข้อมูลนั้นออกจาก "คำจำกัดความของที่เก็บข้อมูลฟิลด์" ได้
สารละลาย:
ตาม @Clive วิธีแก้ไขคือการรับคลาสพื้นที่เก็บข้อมูลสำหรับเอนทิตีแต่ละประเภท จากนั้นใช้เพื่อดึงข้อมูลการแมปตาราง วิธีนี้ใช้ได้ดีกับฟิลด์ที่ไม่ใช่ฐาน แต่ถ้าคุณต้องการฟิลด์ฐาน โซลูชันจะแตกต่างออกไป นี่คือสิ่งที่ฉันลงเอยด้วย:
$ฟิลด์ = [];
foreach ($this->getContentEntityTypes() เป็น $contentEntityType) {
$tableMapping = $this->entityTypeManager->getStorage($contentEntityType->id())->getTableMapping();
foreach ($this->entityFieldManager->getFieldStorageDefinitions($contentEntityType->id()) เป็น $field) {
// เราใช้ needDedicatedTableStorage() เพื่อกรองฟิลด์พื้นฐาน
ถ้า ($tableMapping->requiresDedicatedTableStorage($field)) {
$fieldInfo = [
'ชื่อ' => $field->getName(),
'type' => $field->getType(),
'table' => $tableMapping->getDedicatedDataTableName($ฟิลด์)
];
ถ้า ($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) {
ถ้า (อินสแตนซ์ $entityType ของ ContentEntityTypeInterface && in_array(SqlEntityStorageInterface::class, class_implements($entityType->getStorageClass()))) {
$contentEntityTypes[] = $entityType;
}
}
ส่งคืน $contentEntityTypes;
}