Nicolas Appriou
Nicolas Appriou

Reputation: 2331

Store array of doctrine Document into an Entity

I need to store an array of Document (doctrine ODM) into an Entity stored in relational database (Doctrine ORM). I choose to store the identifiers of my Documents as a string containing a comma separated list of Document identifiers.

I found that I can add a PostLoad event on the ORM side to lazy load my documents: http://docs.doctrine-project.org/projects/doctrine-mongodb-odm/en/1.2.x/cookbook/blending-orm-and-mongodb-odm.html

But the DocumentManager::getReference method only allows to load a single object. Isn't it any way to build something similar to fetch a list of objects ?

Upvotes: 1

Views: 293

Answers (1)

Korri
Korri

Reputation: 657

I would do it by creating a new collection extending Doctrine\Common\Collections\AbstractLazyCollection;

Example code (not tested):

<?php

use Doctrine\Common\Collections\AbstractLazyCollection;
use Doctrine\ODM\MongoDB\DocumentManager;

class LazyArrayRelationshipCollection extends AbstractLazyCollection
{
    private $dm;

    private $className;

    private $ids;

    public function __construct(DocumentManager $dm, $className, array $ids)
    {
        $this->dm = $dm;
        $this->className = $className;
        $this->ids = $ids;
    }

    protected function doInitialize()
    {
        $class = $this->dm->getClassMetadata($this->className);

        $this->collection = $this->dm->getRepository($this->className)
            ->findBy([$class->identifier[0] => $this->ids]);
    }
}

And subscriber:

<?php

use Doctrine\ODM\MongoDB\DocumentManager;
use Doctrine\ORM\Event\LifecycleEventArgs;

class MyEventSubscriber
{
    public function __construct(DocumentManager $dm)
    {
        $this->dm = $dm;
    }

    public function postLoad(LifecycleEventArgs $eventArgs)
    {
        $order = $eventArgs->getEntity();
        $em = $eventArgs->getEntityManager();
        $productReflProp = $em->getClassMetadata(Entities\Order::class)
            ->reflClass->getProperty('products');
        $productReflProp->setAccessible(true);
        $productReflProp->setValue(
            $order, new LazyArrayRelationshipCollection($this->dm, Documents\Product::class, $order->getProductIds())
        );
    }
}

Or you could go a more "dirty" way and loop over you ids, call DocumentManager::getReference on each of them, and return an ArrayCollection of those, it would probably work to.

Upvotes: 0

Related Questions