Problem/Motivation
ReferencedEntityListBuilder::buildRow() is called once per row in the listing. On every call it invokes getStorageByEntityType(), which executes database queries to discover all entity types and fields that reference the current subentity type. With N rows in the table, this means N redundant sets of identical queries — a classic N+1 problem.
public function buildRow(EntityInterface $entity) {
// Called for every row — runs DB queries on each iteration.
$handler = $this->entityTypeManager->getHandler($this->entityTypeId, 'parent');
$storage_by_entity_type = $handler->getStorageByEntityType();
...
}
A secondary issue in the same loop: when a subentity is referenced by more than one parent, $row['parent'] is overwritten on each iteration and only the last parent is displayed.
Proposed resolution
Cache the result of getStorageByEntityType() in a lazy-initialized property so the queries run exactly once per page render regardless of the number of rows.
/**
* @var array<string, \Drupal\field\FieldStorageConfigInterface[]>|null
*/
protected ?array $storageByEntityType = NULL;
protected function getStorageByEntityType(): array {
if ($this->storageByEntityType === NULL) {
/** @var \Drupal\subentity\Entity\EntityParentHandler $handler */
$handler = $this->entityTypeManager->getHandler($this->entityTypeId, 'parent');
$this->storageByEntityType = $handler->getStorageByEntityType();
}
return $this->storageByEntityType;
}
buildRow() then calls $this->getStorageByEntityType() instead of going through the handler directly.
Fix the parent overwrite at the same time by collecting all parents into an array instead of overwriting the cell on each iteration.
Remaining tasks
- Add the
$storageByEntityTypelazy property andgetStorageByEntityType()method toReferencedEntityListBuilder. - Update
buildRow()to use the new method and to accumulate multiple parents instead of overwriting. - Add a kernel test asserting that the listing renders correctly with multiple rows and with a subentity that has more than one parent.
Issue fork subentity-3593907
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #3
anfor commentedComment #5
macsim commentedNice work
Can be merged after applying the suggestion.
Comment #7
macsim commentedApplied it myself and merged it into 3.0.x
Comment #9
macsim commentedComment #10
macsim commented