Problem/Motivation

The proliferation of UUIDs in both GraphQL and JSON:APIs make the scenario of receiving an array of UUIDs as input. The entity repository can already be used to load a single entity by uuid (EntityRepository::loadEntityByUuid) but using this to load groups of entities is inefficient.

An example use case would be assigning a bunch of tags to a piece of content or adding a lot of users to a group through a mutation. Here the tags or users can be provided as an array of UUIDs.

Steps to reproduce

Proposed resolution

Introduce a EntityRepository::loadEntitiesByUuids method that can load multiple entities of the same type from an array of UUIDs. Behaviour for invalid UUIDs will match the behaviour of EntityStorageInterface::loadMultiple where the array of loaded entities may have a smaller size than the input array of UUIDs and only entities with a valid UUID will be loaded. An empty array of UUIDs will not be supported.

Since adding methods to EntityRepositoryInterface would constitute a breaking change, this change is either limited to 10.0.0 unless a backwards compatible way can be thought of. One method may be adding a separate interface in Drupal 9, but this would complicate the update to Drupal 10 where that interface would stop to exist.

Remaining tasks

  • Figure out if it's possible to backport this to 9.x in some way for its utility value
  • Implement test coverage
  • Implement functionality
  • Add change record

User interface changes

None

API changes

Drupal's EntityRepository service now has a loadEntitiesByUuids that can load multiple entities of the same type from an array of UUIDs.

Data model changes

None

Release notes snippet

Comments

Kingdutch created an issue. See original summary.

kingdutch’s picture

Assigned: kingdutch » Unassigned
Status: Active » Needs review
StatusFileSize
new4.72 KB

Attached is a patch that changes EntityRepositoryInterface which unfortunately makes it backwards incompatible.

kingdutch’s picture

StatusFileSize
new4.72 KB
rolki’s picture

Changes look good to me, also I think it is a good idea to add this ability to load multiple entities by UUID. Hope it will be added in the nearest future.

The only thing that should be fixed is "ore", should be "or" in EntityRepositoryInterface.php line 31.

ranjith_kumar_k_u’s picture

StatusFileSize
new4.72 KB

Fixed typo

jeroent’s picture

Status: Needs review » Needs work

Tests fail because of:

1) Drupal\Tests\system\Functional\Module\InstallUninstallTest::testInstallUninstall
PHPUnit\Framework\Exception: Fatal error: Declaration of Drupal\Core\Entity\EntityRepository::loadEntitiesByUuids(string $entity_type_id, array $uuids): array must be compatible with Drupal\Core\Entity\EntityRepositoryInterface::loadEntitiesByUuids($entity_type_id, $uuids): array in /var/www/html/core/lib/Drupal/Core/Entity/EntityRepository.php on line 64
imalabya’s picture

Status: Needs work » Needs review
StatusFileSize
new4.71 KB
new665 bytes

Updated the patch to fix the error.

Status: Needs review » Needs work

The last submitted patch, 7: 3214923-7.patch, failed testing. View results

BS Pavan’s picture

Status: Needs work » Needs review
StatusFileSize
new1.14 KB
new4.91 KB

When fixing the issue of #7, i noticed that, loadByProperties for field_config cannot take array of values.

Observation:
In FieldConfigStorage.php, line number 141 the foreach statement cannot take multiple array of uuid values. So I think we need to individually pass uuid value to loadByProperties method in EntityRepository class

Please check and let me know if I have analysed correctly.

Thanks

Status: Needs review » Needs work

The last submitted patch, 9: 3214923-9.patch, failed testing. View results

dhirendra.mishra’s picture

Status: Needs work » Needs review
StatusFileSize
new725 bytes
new4.67 KB

May be below one would be helpful.

BS Pavan’s picture

StatusFileSize
new1.21 KB
new4.98 KB

Fixing test case failure

berdir’s picture

Status: Needs review » Needs work
+++ b/core/lib/Drupal/Core/Entity/EntityRepository.php
@@ -54,15 +54,28 @@ public function __construct(EntityTypeManagerInterface $entity_type_manager, Lan
     }
-
-    $entities = $this->entityTypeManager->getStorage($entity_type_id)->loadByProperties([$uuid_key => $uuid]);
-
-    return ($entities) ? reset($entities) : NULL;
+    $entities = [];
+    foreach ($uuids as $ukey => $uuid_value) {
+      $uuid_key_value = [];
+      $entities_by_id = $this->entityTypeManager->getStorage($entity_type_id)->loadByProperties([$uuid_key => $uuid_value]);
+      $uuid_key_value = array_keys($entities_by_id);
+      if (isset($uuid_key_value[0])) {
+        $entities[$entities_by_id[$uuid_key_value[0]]->uuid()] = $entities_by_id[$uuid_key_value[0]];
+      }

this implementation actually doesn't make it more efficient at all. I see that it was done above due to a problem with config entities. We could try if an entity query works better, but it's already transformed to that internally anyway. Last resort would be to only do a bulk load for content entities, but without doing that, this IMHO is pointless and doesn't provide any improvement compared to just calling loadEntityByUuid() in a loop.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

geek-merlin’s picture

To fix #13, the for loop should be replaced with sth like:

$entities = $this->entityTypeManager->getStorage($entity_type_id)->loadByProperties([$uuid_key => $uuids]);

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.