How to check if entity changed in Doctrine 2?

eagleoneraptor picture eagleoneraptor · May 29, 2012 · Viewed 38.8k times · Source

I need to check if a persisted entity has changed and needs to be updated on the database. What I made (and did not work) was the following:

$product = $entityManager->getRepository('Product')->find(3);
$product->setName('A different name');

var_export($entityManager->getUnitOfWork()->isScheduledForUpdate($product));

That code prints always false, I also tried to flush before check the unit of work, but did not work.

Anyone has a suggestion?

Answer

Sergi picture Sergi · May 29, 2012

The first thing I'd check it that your setName function is actually doing something ($this-> name = $name...) If it's already working, then you could define an event listener on your services.yml that is triggered when you call the flush.

entity.listener:
  class: YourName\YourBundle\EventListener\EntityListener
  calls:
    - [setContainer,  ["@service_container"]]
  tags:
    - { name: doctrine.event_listener, event: onFlush }

Then you define the EntityListener

namespace YourName\YourBundle\EventListener;

use Doctrine\ORM\Event;
use Symfony\Component\DependencyInjection\ContainerAware;

class EntityListener extends ContainerAware
{   

    /**
     * Gets all the entities to flush
     *
     * @param Event\OnFlushEventArgs $eventArgs Event args
     */
    public function onFlush(Event\OnFlushEventArgs $eventArgs)
    {   
        $em = $eventArgs->getEntityManager();
        $uow = $em->getUnitOfWork();

        //Insertions
        foreach ($uow->getScheduledEntityInsertions() as $entity) {
            # your code here for the inserted entities
        }

        //Updates
        foreach ($uow->getScheduledEntityUpdates() as $entity) {
            # your code here for the updated entities
        }

        //Deletions
        foreach ($uow->getScheduledEntityDeletions() as $entity) {
            # your code here for the deleted entities
        }
    }
}

If you need to know which entities are being changed, but do something with them after they've been saved to the database, just store the entities changed in a private array, an then define a onFlush event that gets the entities from the array.

BTW, to trigger this kind of events you need to add the @ORM\HasLifecycleCallbacks on the entity.