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.
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.
Track field changes on Doctrine entity
Don't use preUpdate or postUpdate, you will have problems. Take a look at onFlush instead.
You have access to the complete changeset at this point, so you can find out what fields have changed, what's been added etc. You can also safely persist new entities. Note as the docs say, you will have to recompute change sets when you persist or change entities.
Simple example I knocked together, not tested but something similar to this will get you what you want.
public function onFlush(OnFlushEventArgs $args) {
$entityManager = $args->getEntityManager();
$unitOfWork = $entityManager->getUnitOfWork();
$updatedEntities = $unitOfWork->getScheduledEntityUpdates();
foreach ($updatedEntities as $updatedEntity) {
if ($updatedEntity instanceof YourEntity) {
$changeset = $unitOfWork->getEntityChangeSet($updatedEntity);
if (array_key_exists('someFieldInYourEntity', $changeset)) {
$changes = $changeset['someFieldInYourEntity'];
$previousValueForField = array_key_exists(0, $changes) ? $changes[0] : null;
$newValueForField = array_key_exists(1, $changes) ? $changes[1] : null;
if ($previousValueForField != $newValueForField) {
$yourChangeTrackingEntity = new YourChangeTrackingEntity();
$yourChangeTrackingEntity->setSomeFieldChanged($previousValueForField);
$yourChangeTrackingEntity->setSomeFieldChangedTo($newValueForField);
$entityManager->persist($yourChangeTrackingEntity);
$metaData = $entityManager->getClassMetadata('YourNameSpace\YourBundle\Entity\YourChangeTrackingEntity');
$unitOfWork->computeChangeSet($metaData, $yourChangeTrackingEntity);
}
}
}
}
}
Related Topics
PHP: Storing 'Objects' Inside the $_Session
Manipulate a String That Is 30 Million Characters Long
How to Extract Text from Word File .Doc,Docx,.Xlsx,.Pptx PHP
Utf-8 Bom Signature in PHP Files
Convert a Comma-delimited String into Array of Integers
How to Get the Content-type of a File in PHP
How to Iterate Over the Results in a MySQLi Result Set
What Are Register_Globals in PHP
Implode an Array With ", " and Add "And " Before the Last Item
Calling PHP Functions Within Heredoc Strings
Incorrect Integer (2147483647) Is Inserted into MySQL
How to Return Integer and Numeric Columns from MySQL as Integers and Numerics in PHP
Remove Script Tag from HTML Content
Finding the Subsets of an Array in PHP
Mixing a PHP Variable With a String Literal