Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Doctrine2 Entites - Is it possible to compare a "dirty" object to one from the database

Is it possible to compare the state of an entity object between the current "dirty" version (an object that has some of its properties changed, not yet persisted) and the "original" version (the data still in the database).

My assumption was that I could have a "dirty" object, then pull a fresh one from the DB and compare the two. For instance:

$entity = $em->getRepository('MyContentBundle:DynamicContent')->find($id);

$editForm = $this->createContentForm($entity);
$editForm->bind($request);

if ($editForm->isValid()) {
    $db_entity = $em->getRepository('MyContentBundle:DynamicContent')->find($id);

    // compare $entity to $db_entity

    $em->persist($entity);
    $em->flush();

    return $this->redirect($this->generateUrl('content_edit', array('id' => $id)));
}

But in my experience, $entity and $db_entity are always the same object (and have the same data as $entity, after the form $request bind). Is there a way to get a fresh version of the $entity alongside the "dirty" version for comparison's sake? The solutions I've seen all pull the needed data before the form bind happens, but I'd rather not have that limitation.

Update: To clarify, I'm looking not only for changes to the entities' properties but also its related collections of entities.

like image 407
Dave Lancea Avatar asked Mar 13 '13 14:03

Dave Lancea


2 Answers

You can get what has changed on the entity through Doctine's UnityOfWork. It is quite simple : after you persisted the entity, Doctrine knows what to update in the database. You can get these informations by doing :

// Run these AFTER persist and BEFORE flush
$uow = $em->getUnitOfWork();
$uow->computeChangeSets();
$changeset = $uow->getEntityChangeSet($entity);
like image 199
Gmajoulet Avatar answered Oct 21 '22 05:10

Gmajoulet


After you flush the $em it happens (it is commited) in database.. so... you might want to retrieve the $db_entity before flush()


  1. I am not sure what you want.. but you can also use merge instead of persist.

    • merge is returning the object modified - id generated and setted
    • persist is modifying your instance
  2. If you want to have the object modified and not persisted use it before flush.

  3. EntityManager is giving you the same instance because you didn't $em->clear()
    • flush is commiting all changes (all dirty objects)
    • clear is clearing memory cache. so when you find(..., $id) , you will get a brand new instance
  4. Is clone keyword working for you? like in this example:

$entity = $em->find('My\Entity', $id);
$clonedEntity = clone $entity;

And you might also want to read this: Implementing Wakeup or Clone

like image 45
Alex Avatar answered Oct 21 '22 05:10

Alex