Hi,
it try to combine some orm and odm stuff. All examples i made are done with the phpcr-odm. I try to understand the lazy-loading of collections, cause i need to do same when loading documents that are referenced by an entity.
But from beginning: When i understand it right, doctrine helps while loading collections. It doesn't query for every item in a collection if it isn't realy needed, means if it isn't asked for. Atm i create a project where i need to load some documents that are referenced in an entity on my own. All references in one world (ORM or ODM) will end up with a list of proxies. But as i am loading the document on my own i would like to have an equal solution for that.
But how do i load the documents? I have stored an uuid of the documents in every entity, so i have got a (almost) unique reference. I created a DocumentAwareEntityInterface
that looks like that:
/**
* This interface helps to combine the ORM world with the ODM world.
*
* Entities which implement this interface are able to reference a document by its uuid.
* This uuid will be persisted into the relational entity. On the other hand the document
* is fetched from the document repository on an preLoad event and back on an
* preUpdate/perPersist event.
*
* To make reusable a EntityAwareDocumentInterface will be created too. By doing this
* we are able to handle it in both world.
*
* @author Maximilian Berghoff <[email protected]>
*/
interface DocumentAwareEntityInterface
{
/**
* Simple setter for the referenced document.
*
* @param EntityAwareDocumentInterface
*/
public function setDocumentNode(EntityAwareDocumentInterface $document);
/**
* Simple getter for the referenced document
*
* @return EntityAwareDocumentInterface
*/
public function getDocumentNode();
/**
* Getter for the uuid of the referenced document.
*
* @return $uuid
*/
public function getUuid();
/**
* Setter for the uuid of the referenced document.
*
* @param $uuid
*/
public function setUuid($uuid);
}
As you can see, i have got an interface for the "other" side too. But that doesn't matter atm.
I created an eventlistener on postLoad
:
/**
* When an entity was loaded that implements the DocumentAwareEntityInterface
* we will fetch the content by it uuid from the document repository an store it instead of the
* uuid to the entity
*/
public function postLoad(LifecycleEventArgs $eventArgs)
{
$entity = $eventArgs->getObject();
if ($entity instanceof DocumentAwareEntityInterface) {
$uuid = $entity->getUuid();
if (!UUIDHelper::isUUID($uuid)) {
return;
}
$document = $this->getDocumentManager()->find(null, $uuid);
if (null === $document) {
return;
}
$entity->setDocumentNode($document);
$entity->setTitle($document->getTitle());
}
}
As you can see my entity has a field for title too. So i do not need to query the document when just displaying the entity in a list or selection. Quite dirty but it's ok.
For addition only i got an listener on postUpdate
too:
/**
* When an entity is persisted or updated we need to take care of the entire document.
* This one needs to be persisted/updated too.
*
* @param \Doctrine\ORM\Event\LifecycleEventArgs $eventArgs
*/
public function preUpdate(LifecycleEventArgs $eventArgs)
{
$entity = $eventArgs->getObject();
if ($entity instanceof DocumentAwareEntityInterface) {
$document = $entity->getDocumentNode();
if ($document instanceof EntityAwareDocumentInterface) {
$this->getDocumentManager()->persist($document);
$this->getDocumentManager()->flush();
}
}
}
The one for "create new" isn't realy ready, cause i have issues with the parent/position setting for a new document.
That works fine for me, but to fine. Cause: A collection of those entites will query the odm part of the database for every entity. Means in my case: i got a select-field (entiy-form-type) with 2k Entites -> 2k queries to get the document, what is quite uncool.
So,...
What i would need now is to learn how the lazy loading works and how it is implemented. I want to query when $entity->getDocument()
is called only.
This example could end up in a proposal to combine orm and odm world. I do not know if the other odm implementation has got an equal way for referencing, but the phpcr-odm has it.
You would ask: Why the hell is he doing that? Cause i got a structure where have tons of relations (-1 for odm) but would need versioning and translations for some properties (+1 for odm). So i wanne combine that stuff.
What do you think?
I think i will need some kind of class metadata mapping for that to know the documents/enties. Btw. this would solve my position/parent problem on create too.