#Purpose of the DoctrineOrmOdmAdapter
tasks:
- persist referenced object out of the box, when an object is persisted
- update referenced object out of the box, when object is updated and referenced object has changed
- remove referenced object out of the box, when object is removed
- load just a reference/proxy of the referenced object, when the object is loaded
As you can see i just speak about an object and an referenced object. I do want to keep all various doctrine implementation stuff out of it. When referencing an phpcr-odm document on an an orm entity, then the object would be the entity and the referenced object the document:
$productEntity = new ProductEntity();
$productDocument = new ProductDocument();
$productDocument->setTitle('My new and awesome product');
$productDocument->setBody('....');
// add some phpcr specific stuff
...
$productEntity->setDocument($productDocument);
$productEntity->addGroup(...);
$productEntity->addPriceLists(...);
$entityManager->persist($productEntity);
That's all! I do not want to write more then this combined with a mapping like that:
/**
* @ORM\Entity
* @ORM\Table(name="object")
* @ODMAdapter\ObjectAdapter
*/
class ProductEntity
{
/**
* @ORM\Id()
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\Column(type="string")
*/
public $uuid;
/**
* @var object
* @ODMAdapter\ReferencePhpcr(
* referencedBy="uuid",
* inversedBy="uuid",
* targetObject="ProductDocument",
* name="document",
* commonField={
* @ODMAdapter\CommonField(referencedBy="title", inversedBy="title")
* }
* )
*/
public $document;
/**
* @ORM\Column(type="string")
*/
public $title;
}
So that works fine (xml is done, yml planed). I got an bundle (https://github.com/ElectricMaxxx/DoctrineOrmPhpcrAdapterBundle) that would handle that use-case. It just injects the Entity-/DocumentRegistry by a configuration into a so called ObjectAdapterManager
(in https://github.com/ElectricMaxxx/DoctrineOrmOdmAdapter) similar to the common ObjectManager configuration.
The bundle serves a listener for ORM/PHPCR-ODM lifecycle events, which just calls the ObjectAdapterManager
to trigger the persistence operations. Those hard work is done by an own UnitOfWork
, which is able to fire own events.
That is just a short example how it works. And it does working. All operations are triggered. I do just have got an issue with the inconsistent use of id/uuid in phpcr-odm's UoW. But one step back:
As i do not wanna really load a referenced object onLoad of the object (incredible performance issues), i decided (with the help of @Ocramius) to use the getReference()
method on the manager that is responsible for the referenced object. That method needs the className
and id
as a parameter. And so the trouble beginns....
If i reference an orm entity i will reference on it's id, which is the mapped identifier too. If i reference a phpcr-odm document i will definitely reference the document's uuid. But when injecting that into $dm->getReference('className', $uuid);
i got an exception cause:
When retrieving the document by doing an $entity->getDocument()->getTitle()
the ODM's UoW calls $node = $this->session->getNode($this->determineDocumentId($document));
. As i injected the uuid as id into the proxy the UoW tries to the document's node by that, which is impossible cause the session wanna have the path-identifier.
The decisions would be here:
- chance to let the UoW use
$this->session->getNodeByIdentifier($uuid);
in case of an uuid (as the$dm->find()
does) or is that inconsistency hidden somewhere else in the UoW - crate an own proxy for referenced and lazy-loading object, which calls the responsible manager's
find()
method. That would cause redundant data
Btw i know that the document's uuid and the id arn't the same. So the word inconsistency is maybe wrong. But i think as the DocumentManager allows to fetch a document by its uuid all methods should allow that.