Skip to content

Collections as first class members #6311

Open
@backbone87

Description

@backbone87

This is just some quick thought that came to my mind: Collections as first class members. I post it to get some feedback.

This issue is just a grand view of how things could be done when dealing with collections, but some features may be useful on its own.

  • Directly asking the EM/ER for a specific collection, which returns a Collection reference:
$collection = $em->getCollection(Category::class, $categoryId, 'products', $asExtraLazy);
$collection = $categoryRepository->getCollection($categoryId, 'products', $asExtraLazy);
  • Extending DQL to mark collection "pre fetches":
$q = $em->createQuery('SELECT p FROM Products p WHERE p.category IN (:categories)');
$q->setHint(Query::HINT_COLLECTION, [
  'entity' => Category::class,
  'collection' => 'products',
]);
$q->setParam('categories', [ 1, 2 ]);
$products = $q->getResult();
$category = $em->getReference(Category::class, 1);
$productCollection1 = $em->getCollection(Category::class, 1, 'products');
$category->getProducts() === $productCollection1;
$productCollection1->toArray(); // does not hit DB, since we prefetched the collection earlier
  • Partial collection loading via DQL:
$q = $em->createQuery('SELECT p FROM Products p WHERE p.category IN (:categories) AND p.pinned');
$q->setHint(Query::HINT_COLLECTION, [
  'entity' => Category::class,
  'collection' => 'products',
  'partial' => true,
]);
$q->setParam('categories', [ 1, 2 ]);
$products = $q->getResult();
$category = $em->getReference(Category::class, 1);
$productCollection1 = $em->getCollection(Category::class, 1, 'products');
$category->getProducts() === $productCollection1;
$productCollection1->get($products[0]->getId()); // does not hit DB, since we prefetched the partial collection earlier
  • Criteria collection prefetch:
$criteria = Criteria::create()->where(Criteria::expr()->eq('pinned', true));
$q = $em->createQuery('SELECT p FROM Products p WHERE p.category IN (:categories) AND p.pinned');
$q->setHint(Query::HINT_COLLECTION, [
  'entity' => Category::class,
  'collection' => 'products',
  'criteria' => $criteria,
]);
$q->setParam('categories', [ 1, 2 ]);
$products = $q->getResult();
$category = $em->getReference(Category::class, 1);
$productCollection1 = $em->getCollection(Category::class, 1, 'products');
$category->getProducts()->filter($criteria) === $productCollection1->filter($criteria); // optional feature
$productCollection1->filter($criteria)->toArray(); // does not hit DB, since we prefetched the collection with this criteria earlier
  • Adding entities to collections, without loading the collection (or the entity). Similar for deletes. Though this feature could be dropped and handle first class collections as read only.
$productCollection = $em->getCollection(Category::class, 1, 'products');
$product = $em->getReference(Product::class, 1);
$productCollection->add($product);
  • All this allows easy multi-step hydration
  • Implement EAGER collection as multi-step hydration by default

https://ocramius.github.io/blog/doctrine-orm-optimization-hydration/

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions