I am working an Symfony 2.8
based web app project which currently uses Doctrine 2
. The project is basically a simple ToDo list application which can be synced with a mobile app (iOS/Android).
While reading the Update notes of Doctrine 3
I discovered, that EntityManager::merge
will no longer be supported.
An alternative to EntityManager#merge() is not provided by ORM 3.0, since the merging semantics should be part of the business domain rather than the persistence domain of an application. If your application relies heavily on CRUD-alike interactions and/or PATCH restful operations, you should look at alternatives such as JMSSerializer.
I am not sure what is the best/correct way to replace EntityManager::merge
?
Where do I use merge:
During the sync of the mobile apps with the web app the data is transferred as serialized JSON which is than de-serialized by JMSSerializer
to an entity object. When the web app receives a ToDoEntry
object this way, it can be a new ToDo-Entry (not known in the web app yet) or an updated existing entry. Either way, the received object is not managed by the EntityManager
. Thus $em->persist($receivedObject)
will always try to insert a new object. This will fail (due to the unique constraint of the id) if the ToDo-Entry already exists in the web app and needs to be updated.
Instead $em->merge($receivedObject)
is used which automatically checks wether an insert or update is required.
Hot wo solve this?
Of course I could check for every received objects if an entity with the same ID already exists. In this case could load the existing object and update its properties manually. However this would be very cumbersome. The real project of course uses many different entities and each entity type/class would need its own handling to check which properties needs to be updated. Isn't there a better solution?
The EntityManager is the central access point to ORM functionality. It can be used to find, persist, flush and remove entities.
Doctrine uses the Identity Map pattern to track objects. Whenever you fetch an object from the database, Doctrine will keep a reference to this object inside its UnitOfWork. The array holding all the entity references is two-levels deep and has the keys root entity name and id.
A repository mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects. In Doctrine, a repository is a class that concentrates code responsible for querying and filtering your documents.
The Doctrine Project is the home to several PHP libraries primarily focused on database storage and object mapping. The core projects are the Object Relational Mapper (ORM) and the Database Abstraction Layer (DBAL) it is built upon. Get Started View Projects.
You can try to use registerManaged() method of Doctrine\ORM\UnitOfWork.
// $this->em <--- Doctrine Entity Manager
// $entity <--- detached Entity (and we know that this entity already exists in DB for example)
$id = [$entity->getId()]; //array
$data = $entity->toArray(); //array
$this->em->getUnitOfWork()->registerManaged($entity, $id, $data);
Of course, You can check the state of Your Entity using getEntityState() of Doctrine\ORM\UnitOfWork before/after perfoming needed actions.
$this->eM->getUnitOfWork()->getEntityState($entity, $assert = 3)
$assert <-- This parameter can be set to improve performance of entity state detection by potentially avoiding a database lookup if the distinction between NEW and DETACHED is either known or does not matter for the caller of the method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With