Is there a built-in way to get all of the changed/updated fields in a Doctrine 2 entity
You can useDoctrine\ORM\EntityManager#getUnitOfWork
to get a Doctrine\ORM\UnitOfWork
.
Then just trigger changeset computation (works only on managed entities) via Doctrine\ORM\UnitOfWork#computeChangeSets()
.
You can use also similar methods like Doctrine\ORM\UnitOfWork#recomputeSingleEntityChangeSet(Doctrine\ORM\ClassMetadata $meta, $entity)
if you know exactly what you want to check without iterating over the entire object graph.
After that you can use Doctrine\ORM\UnitOfWork#getEntityChangeSet($entity)
to retrieve all changes to your object.
Putting it together:
$entity = $em->find('My\Entity', 1);$entity->setTitle('Changed Title!');$uow = $em->getUnitOfWork();$uow->computeChangeSets(); // do not compute changes if inside a listener$changeset = $uow->getEntityChangeSet($entity);
Note. If trying to get the updated fields inside a preUpdate listener, don't recompute change set, as it has already been done. Simply call the getEntityChangeSet to get all of the changes made to the entity.
Warning: As explained in the comments, this solution should not be used outside of Doctrine event listeners. This will break Doctrine's behavior.
Check this public (and not internal) function:
$this->em->getUnitOfWork()->getOriginalEntityData($entity);
From doctrine repo:
/** * Gets the original data of an entity. The original data is the data that was * present at the time the entity was reconstituted from the database. * * @param object $entity * * @return array */public function getOriginalEntityData($entity)
All you have to do is implement a toArray
or serialize
function in your entity and make a diff. Something like this :
$originalData = $em->getUnitOfWork()->getOriginalEntityData($entity);$toArrayEntity = $entity->toArray();$changes = array_diff_assoc($toArrayEntity, $originalData);
Big beware sign for those that want to check for the changes on the entity using the method described above.
$uow = $em->getUnitOfWork();$uow->computeChangeSets();
The $uow->computeChangeSets()
method is used internally by the persisting routine in a way that renders the above solution unusable. That's also what's written in the comments to the method: @internal Don't call from the outside
.After checking on the changes to the entities with $uow->computeChangeSets()
, the following piece of code is executed at the end of the method (per each managed entity):
if ($changeSet) { $this->entityChangeSets[$oid] = $changeSet; $this->originalEntityData[$oid] = $actualData; $this->entityUpdates[$oid] = $entity;}
The $actualData
array holds the current changes to the entity's properties. As soon as these are written into $this->originalEntityData[$oid]
, these not yet persisted changes are considered the original properties of the entity.
Later, when the $em->persist($entity)
is called to save the changes to the entity, it also involves the method $uow->computeChangeSets()
, but now it won't be able to find the changes to the entity, as these not yet persisted changes are considered the original properties of the entity.