Get previous value of Doctrine collection
Understanding PersistentCollection
If you have an entity with a OneToMany
or ManyToMany
Doctrine association, the collection you get back (e.g., $user->getComments()
isn’t just a plain ArrayCollection
. It’s a Doctrine\Orm\PersistentCollection
instance which is a special wrapper that:
- Lazily loads related entities only when needed
- Tracks changes to the collection in memory
- Helps Doctrine know what to insert, update or delete on flush
Understanding PersistentCollection::getSnapshot()
PersistentCollection::getSnapshot()
returns an array of the collection’s contents exactly as they were when Doctrine last loaded or synchronised them with the database. Doctrine sets this snapshot when it loads the collection from the DB (either via the initial load or via a refresh (EntityManager::refresh($entity)
or flush).
So when the collection is first loaded or later synchronised with the database, Doctrine takes a snapshot of it and stores it as a “snapshot”. You can access this snapshot via PersistentCollection::getSnapshot()
. This means that if you load a User
object with 2 Comment
records and then add a third comment record, $user->getComments()
will return 3 records (the new amount in memory) but $user->getComments()->getSnapshot()
will return 2 records (the original amount).
This snapshot representation also helps Doctrine calculate what changes to perform when you flush your changes.
Here’s an example usage of PersistentCollection::getSnapshot()
:
$comments = $userr->getComments(); // PersistentCollection
// Original snapshot when entity was loaded:
$original = $comments->getSnapshot(); // e.g. [Comment#1, Comment#2]
// Add a new one in memory:
$comments->add($newComment);
// Current collection: [Comment#1, Comment#2, Comment#3]
// Snapshot (unchanged): [Comment1#1, Comment2#2]
$added = $comments->getInsertDiff(); // [Comment#3]
$removed = $comments->getDeleteDiff(); // []
Other helpers: getInsertDiff()
and getDeleteDiff()
PersistentCollection::getInsertDiff()
: returns items that are in the current collection but not in the snapshot.PersistentCollection::getDeleteDiff()
: returns items that are not in the current collection but were in the snapshot.