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 $storageByEntityType lazy property and getStorageByEntityType() method to ReferencedEntityListBuilder.
  • 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

Command icon 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

macsim created an issue. See original summary.

anfor made their first commit to this issue’s fork.

anfor’s picture

Assigned: Unassigned » macsim
Status: Active » Needs review

macsim’s picture

Assigned: macsim » anfor
Status: Needs review » Needs work

Nice work
Can be merged after applying the suggestion.

  • macsim committed da55d721 on 3.0.x authored by anfor
    task: #3593907 Retrieve storage entity type config in render method
    
macsim’s picture

Assigned: anfor » Unassigned
Status: Needs work » Fixed

Applied it myself and merged it into 3.0.x

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

macsim’s picture

Version: 3.x-dev » 3.0.x-dev
macsim’s picture

Status: Fixed » Closed (fixed)