Puncte:2

Cum obțin numele tabelelor în care sunt stocate datele de câmp?

drapel cn

În Drupal 7, a fost capabil să recupereze numele fizice ale tabelelor bazei de date folosind un cod ca următorul, a fost destul de simplu.

$field_definitions = field_info_fields();
foreach ($field_definitions as $field => $definition) {
  $current_storage = $definition['storage']['details']['sql'][FIELD_LOAD_CURRENT];
  $tabel_curent = cheie($stocare_curentă);
  $revision_storage = $definition['storage']['details']['sql'][FIELD_LOAD_REVISION];
  $tabel_reviziune = cheie($stocare_reviziune);
}

În Drupal 9, API-ul entității s-a schimbat în bine și acum există clase și servicii pentru a extrage acest tip de informații.Toate acestea sunt bine și bine, înțeleg majoritatea conceptelor din jurul acestui lucru, dar nu pot, pentru viața mea, să par să extrapolez cum să obțin aceleași date.

Scopul meu este să fac bucla peste toate tipurile mele de entități care le implementează ContentEntityTypeInterface, obțineți câmpurile lor, apoi construiți o matrice care să arate așa, am un script Drush foarte specializat pe care încerc să îl port din Drupal 7.

$exemplu = [
  'nod' => [
    'field_something' => [
      'current' => 'un nume_tabel'
      'revision' => 'un nume_tabel'
    ]
  ],
  'bloc' => [
    'field_something' => [
      'current' => 'un nume_tabel'
      'revision' => 'un nume_tabel'
    ]
  ]
];

*Desigur, ținând cont dacă un câmp este de fapt revizuibil, în primul rând.

Pe cont propriu, am stabilit în cea mai mare parte că numele tabelelor ajung să fie ca $entityType . '__' . $field['nume'] și $entityType . '_reviziune__' . $field['nume'] dar codificarea scriptului meu se defectează când sunt folosite ID-uri unice. De exemplu, blocurile personalizate au nume de tabel precum block_content_r__7fe666c7a4. Trebuie să pot extrage acele date din „definiția de stocare a câmpului” de fel.

Soluţie: Pentru @Clive, soluția a fost să obținem clasa de stocare pentru fiecare tip de entitate și apoi să o folosiți pentru a prelua mapările de tabel. Acest lucru funcționează excelent pentru câmpurile care nu sunt de bază, dar dacă doriți un câmp de bază, soluția ar fi diferită. Iată cu ce am ajuns:

$câmpuri = [];
foreach ($this->getContentEntityTypes() ca $contentEntityType) {
  $tableMapping = $this->entityTypeManager->getStorage($contentEntityType->id())->getTableMapping();
  foreach ($this->entityFieldManager->getFieldStorageDefinitions($contentEntityType->id()) ca $câmp) {
    // Folosim requiresDedicatedTableStorage() pentru a filtra câmpurile de bază 
    dacă ($tableMapping->requiresDedicatedTableStorage($câmp)) {
      $fieldInfo = [
        'name' => $field->getName(),
        'type' => $field->getType(),
        'table' => $tableMapping->getDedicatedDataTableName($field)
      ];
      dacă ($câmp->isRevizabil()) {
        $fieldInfo['table_revision'] = $tableMapping->getDedicatedRevisionTableName($field);
      }
      $fields[$contentEntityType->id()][] = $fieldInfo;
    }
  }
}
returnează $câmpuri;

Am scris o metodă separată pentru a obține entitățile mele de conținut, pe care le-a folosit codul de mai sus.

funcția getContentEntityTypes() {
  $contentEntityTypes = [];
  $entity_type_definitions = $this->entityTypeManager->getDefinitions();
  /* @var $definition EntityTypeInterface */
  foreach ($entity_type_definitions ca $entityType) {
    if ($entityType instanceof ContentEntityTypeInterface && in_array(SqlEntityStorageInterface::class, class_implements($entityType->getStorageClass()))) {
      $contentEntityTypes[] = $entityType;
    }
  }
  returnează $contentEntityTypes;
}
Puncte:4
drapel cn

Presupunând un backend de stocare SQL, numele tabelelor sunt disponibile de la TableMappingInterface::getAllFieldTableNames(). Puteți obține maparea tabelului unui tip de entitate din handlerul său de stocare.

Acesta ar putea fi probabil mai elegant, dar ar trebui să fie un bun punct de plecare:

utilizați Drupal\Core\Entity\ContentEntityTypeInterface;
utilizați Drupal\Core\Entity\Sql\SqlEntityStorageInterface;

...

// Aceste servicii ar trebui să fie injectate dacă contextul o permite.
$entity_type_manager = \Drupal::entityTypeManager();
/** @var \Drupal\Core\Entity\EntityFieldManagerInterface $field_manager */
$field_manager = \Drupal::service('entity_field.manager');

$tablele = [];
foreach ($entity_type_manager->getDefinitions() ca $entity_type) {
  // Listează numai tipurile de entități de conținut folosind stocarea SQL.
  if ($entity_type instanceof ContentEntityTypeInterface && in_array(SqlEntityStorageInterface::class, class_implements($entity_type->getStorageClass()))) {
    $storage = $entity_type_manager->getStorage($entity_type->id());

    foreach ($field_manager->getFieldStorageDefinitions($entity_type->id()) ca $field) {
      $tables[$entity_type->id()][$field->getName()] = $storage->getTableMapping()
        ->getAllFieldTableNames($field->getName());
    }
  }
}

Asta vă va obține un rezultat ca acesta:

introduceți descrierea imaginii aici

Probabil că veți dori să faceți niște filtre și să faceți ajustări în interior pentru fiecare buclă pentru a obține rezultatul exact de care aveți nevoie.

drapel cn
Aceasta este perfect! Știam că era prin managerul de câmp al entității, dar nu eram sigur cum să ajung de acolo la maparea tabelului. Voi încerca asta luni și voi vedea cum merg lucrurile! Multumesc mult!
drapel cn
Am aruncat o privire rapidă la asta și a funcționat. Aș presupune că aș putea întreba definiția câmpului dacă este revizuibil și atunci există o metodă pentru a obține acel nume de tabel?
drapel cn
Puteți întreba dacă este revizuibil cu `$field->isRevisionable()`, dar obținerea numelui exact al tabelului este mai complicată deoarece câmpurile de bază pot exista în mai multe tabele. Dacă aveți nevoie doar de câmpuri care nu sunt de bază sau, mai precis, de cele care nu se află în tabelele de bază și de revizuire de bază, puteți utiliza `$storage->getTableMapping()->requiresDedicatedTableStorage($field)` pentru a filtra candidații, atunci utilizați `$storage->getTableMapping()->getDedicatedDataTableName($field)` și `->getDedicatedRevisionTableName($field)` pentru a obține numele tabelelor
drapel cn
Da, a funcționat perfect. Codul meu final a fost adăugat la întrebare. Mulțumesc din nou pentru ajutor!

Postează un răspuns

Majoritatea oamenilor nu înțeleg că a pune multe întrebări deblochează învățarea și îmbunătățește legătura interpersonală. În studiile lui Alison, de exemplu, deși oamenii își puteau aminti cu exactitate câte întrebări au fost puse în conversațiile lor, ei nu au intuit legătura dintre întrebări și apreciere. În patru studii, în care participanții au fost implicați în conversații ei înșiși sau au citit transcrieri ale conversațiilor altora, oamenii au avut tendința să nu realizeze că întrebarea ar influența – sau ar fi influențat – nivelul de prietenie dintre conversatori.