I'm using Doctrine to save user data and I want to have a last modification
field.
Here is the pseudo-code for how I would like to save the form once the user presses Save
:
- start transaction
- do a lot of things, possibly querying the database, possibly not
- if anything will be changed by this transaction
- modify a
last updated
field
- modify a
- commit transaction
The problematic part is if anything will be changed by this transaction
. Can Doctrine give me such information?
How can I tell if entities have changed in the current transaction?
edit
Just to clear things up, I'm trying to modify a field called lastUpdated
in an entity called User
if any entity (including but not limited to User
) will be changed once the currect transaction is commited. In other words, if I start a transaction and modify the field called nbCars
of an entity called Garage
, I wish to update the lastUpdated
field of the User
entity even though that entity hasn't been modified.
Sorry for giving you the wrong answer at first, this should guide you in the right direction (note that it's not perfect).
You'll need to implement two events. One which listens to the OnFlush event, and acts like this:
We need to wait for the OnFlush event, because this is the only opportunity for us to get access to all of the work that is going to be done. Note, I didn't include it above, but there is also
$unitOfWork->getScheduledEntityDeletions()
as well, if you want to track that.Next, you need another final event listener which listens to the PostFlush event, and looks like this:
Once the transaction has been started, it's too late, unfortunately, to get doctrine to save another entity. Because of that, we can make the update to the field of the
User
object in the OnFlush handler, but we can't actually save it there. (You can probably find a way to do this, but it's not supported by Doctrine and would have to use some protected APIs of the UnitOfWork).Once the transaction completes, however, you can immediately execute another quick transaction to update the datetime on the user. Yes, this does have the unfortunate side-effect of not executing in a single transaction.
This is a necessary reply that aims at correcting what @ColinMorelli posted (since flushing within an lifecycle event listener is disallowed - yes, there's one location in the docs that says otherwise, but we'll get rid of that, so please don't do it!).
You can simply listen to
onFlush
with a listener like following:This will apply the change to the configured
User
object only if theUnitOfWork
contains changes to be committed to the DB (an unit of work is actually what you could probably define as an application level state transaction).You can register this subscriber with the ORM at any time by calling
My guess would have been, similarly to the other 2 answers, is to say whatever you want to do when there will or will not be changes, use event listeners.
But if you only want to know before the transaction starts, you can use
Doctrine_Record::getModified()
(link).@PreUpdate
event won't be invoked if there's no change on the entity.