need explanation on postPersist and data flushed - symfony

i had trouble with an entity who was not flushed correctly.
In a service, i setted somme values. before flushing them in the service, i call another service and i saw there was a listener linked.
In this listener, there was a postPersist method in witch was called "$entityManager->flush();"
It was the source of my problem.
I found this post : Doctrine inserting in postPersist event
So, i deleted the flush who was done in the postPersist.
But i don't understand the need of the method postFlush.
In my case, data is flushed even if i don't have this method. how is it possible that the properties setted in the listener are flushed correctly without this event ?
If i look other entry points, i see that i need to declare the postFlush event and i see the need of this method.
thanks for your help

No, you don't need to flush in a postPersist event, because it will be done soon, just after Persist. You don't need to use all the functions of the list, neither declaring them.
ps.: Only if you need to get/set data before persist/flush. You would need to compute changes then get them in the action 'couple' (e.g prePersist and postPersist, preUpdate and postUpdate).
docs says:
Changes to fields of the passed entities are not recognized by the
flush operation anymore, use the computed change-set passed to the
event to modify primitive field values.
and
getEntityChangeSet() to get a copy of the changeset array. Changes to
this returned array do not affect updating.
PostFlush
The postFlush is made at the end of a flush operation. According to the docs this event is not a lifecycle callback. You can use it to set something after registering, or even send notifications, clearly with postFlush you won't need to worry about lifeCycle events.
postFlush - The postFlush event occurs at the end of a flush
operation. This event is not a lifecycle callback.
For postPersist in the docs
postPersist - The postPersist event occurs for an entity after the
entity has been made persistent. It will be invoked after the database
insert operations. Generated primary key values are available in the
postPersist event.
Here you can have ids if you need before flush.
You can check the docs about LifeCycleEvents here:
https://www.doctrine-project.org/projects/doctrine-orm/en/latest/reference/events.html#lifecycle-events

Related

Creating new entities in `postFlush` doctrine event

I'm struggling to find a way to perform a persist() and flush() methods after the final flush (I mainly want to do it in postFlush event).
I collect the necessary entities in onFLush event (with changeSets) and wait up until all entities (which I collected) got flushed to get their id's (auto incremented).
So that I have at this point an array with all needed entities and their change sets and their id's set.
Then I want to create new entities (let's call them "traces") based on fields of previously collected entities and persist & flush "traces" in database.
But I'm really stuck here as I can't know entities id's in onFlush event, and I can't persist & flush them in postFlush when they already have their id's set.
Currently Doctrine documentation states following:
postFlush is called at the end of EntityManager#flush(). EntityManager#flush() can NOT be called safely inside its listeners.
And if I dare do this, it ends up in a recursion and php fails with an error.
Which approach may I take here?
I believe you could do a check if you aren't flushing "traces" entity and then perform your "traces" creation. That shouldn't loop.
Also you might want to look at symfony's eventDispatcher . You could dispatch your events manually, since it might be cleaner.
More details on "traces" would be helpful, from what I can imagine it is some kind of a changelog, history; so for that I might suggest EntityAuditBundle. It works pretty good with doctrine and is not hard to set up, I am using it myself.

Doctrine update event on loaded Entity instance

I have problem with event in Doctrine , i need event on persist object that is already loaded
$obj = $em->getRepository(EntityName::class)->findById($someId);
$obj2 = clone $obj;
$obj2->property = 'some value';
$obj->property = 'some diff value';
$em->persist($obj2);
$em->persist($obj);
I register event in EntityName class on event #PrePersist and that works perfect for $obj2 but event is not fired for $obj, is there way to delete $obj from $em->UnitOfWorks and fire event for $obj.
The trick is that i must fire event before $em->flush()
#PrePersist only triggers when you are inserting a new entity. If you've already found an existing entity like you have above, then you will need to use the #PreUpdate event.
The Doctrine documentation contains information for all these events.
Of course, without knowing what you are attempting to do, and seeing your #PrePersist code, it's impossible to help you further. You might be able to use onFlush like Cerad suggested. You may need both prePersist and preUpdate.
Either way, merely calling $em->persist() does not guarantee that the prePersist event is going to be triggered.

How do I check that a particular lifecycle event method runs in a Doctrine event subscriber?

I have a preUpdate event hook in an event listener and I want to write a test that just verifies that it gets executed when a particular document is updated. The only documentation I've been able to find about testing anything Doctrine-related was about testing query builders. I am new to Doctrine and this seems like a very simple thing to do but I really can't figure it out.
You can use partial mock. Lets say the class that has preUpdate hook is called Entity.
$mock = $this->getMockBuilder('Mock')->setMethods(array('preUpdate'))->getMock();
This create an object for which only the preUpdate method is stubbed and you can write expectations to this method:
$mock->expects($this->once())->method('preUpdate');
// some code that triggers the hook
All other methods of the class will work as in the original class - they would not be overriden

Doctrine / Symfony2 : postSave event?

I have an issue with doctrine 2. I can't find how to achieve a result similar to the function postSave in Doctrine 1.
Basically, what I want to do is to persist, update or remove an entity and once the database is updated I want to perform operation on related entities.
I tried to do it in postPersist, postUpdate and postRemove, but the database is not updated at that point.
I'm using Entity listener, with my own entity listener resolver to inject my own services in my listener.
The onFLush method doesn't seam to work.
On this page http://doctrine-orm.readthedocs.org/en/latest/reference/events.html#entity-listeners there is no mention of postFlush or even onFlush event in entity listener.
If anyone knows how to execute some code AFTER the database is updated I would be very gratefull :)
Thanks in advance.
You need lifecycle callbacks:
Doctrine2 docs
Symfony2 docs
I suspect that you need postUpdate or onFlush (which are described in the first page)
This:
postUpdate - The postUpdate event occurs after the database update operations to entity data. It is not called for a DQL UPDATE statement.
And this:
onFlush - The onFlush event occurs after the change-sets of all managed entities are computed. This event is not a lifecycle callback.

Need Doctrine 2 lifecycle events clarification for encrypting data

So I'm confused about Doctrine 2's lifecycle events. I have a subscriber event class that implements prePersit, preUpdate, postUpdate, and postLoad. Basically what I'm trying to do is to encrypt an entity's particular value on "prePersist" and "preUpdate" (when updating a value), and decrypt the value on "postLoad".
The decryption is working perfectly. However, I'm currently having two problems with these lifecycle events:
when "preUpdate" is triggered, it encrypts the value correctly (looking at my debugger) but once it gets committed to the database, I can see the that value is in clear text. What's the deal here?
I have also implemented the "postUpdate" event, which I was thinking that it would be triggered after the update is committed to the database, which would give me chance to decrypt the value for viewing on the UI, but following the debugger this is not case. The preUpdate is triggered first when doing an update, then followed by postUpdate, and finally this changes are committed to the database. Which event life cycle should I be using for this case?
The signature on preUpdate must be on type PreUpdateEventArgs.
This link has more info on to get it working.

Resources