Question: how to trigger Doctrine lifecycle events in my code, having the entity data available?
Details
I have an active listener on the Doctrine postPersist and postUpdate events.
I cannot modify / override this listener.
In some places in my code, for performance reasons, I use DBAL to save data instead of ORM methods.
I'd like to stick to the same event system.
Thank you in advance for your help.
Extending #Cerad answer, here's a very basic sample code to achieve the result (trigger a Doctrine LifeCycle event). This sample assumes we're in a Symfony controller:
use Doctrine\ORM\Event\LifecycleEventArgs;
// ...
$user = new AppBundle\Entity\User();
// ... do something with the user
$entityManager = $this->getDoctrine()->getManager();
$eventManager = $entityManager->getEventManager();
$eventArgs = new LifecycleEventArgs($user, $entityManager);
$eventManager->dispatchEvent(\Doctrine\ORM\Events::postPersist, $eventArgs);
Assuming you have access to the entity manager then:
$eventManager = $entityManager->getEventManager();
After that you can build and dispatch events per the documentation.
I checked to see if there is a predefined service but did not see one. But you probably define one as a factory and inject it as needed.
Hope this is what you are asking for.
Related
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.
Can anyone tell me how to implement Doctrine NotifyPropertyChanged in Symfony?
I have implemented this code in an Entity that will notify about is changes. But how to add listener for these changes in another Entity?
I mean I want to handle this situation: Entity Book has oneToMany to Authors. When something is being changed in a partcular Author, I want to react on it in a Book Entity. So I have implemented NotifyPropertyChanged in Author. In a setter I invoke notifications, but how to add this listener to a Book entity?
It looks like your use case is a little bit different: the ǸotifyPropertyChanged` is usefull to tell Doctrine your entity changed. By default, Doctrine2 will iterate over all properties and compare them (so that's "automatic"). IMO, drop it. Only use case I see for it right now are some very specific cases were using the default policy would cost too much.
Another way to do would be to use some lifecycle events. Changing other entities from a preUpdate or postUpdate is notoriously difficult. Doctrine already started calculting the "changeset", what to persist to DB, and there's no easy way to add another entity to it.
Since you are ok writing some code inside the setters, the easier path is something like this:
class Author
{
public function setName($name)
{
// ...
// for each setter, call onChanged
$this->onChange();
}
private function onChange()
{
foreach ($this->books as $book) {
// maybe call some method on your books, like onAuthorChanged() ?
}
}
}
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
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.
I have a preUpdate listener for an Entity where I do some calculations, set values etc.
In that listener I would like to remove some other related entities, but this does not seem to be flushed by the entity manager. How can I go about achieving this?
According to the Doctrine2 docs:
Changes to associations of the updated entity are never allowed in
this event, since Doctrine cannot guarantee to correctly handle
referential integrity at this point of the flush operation.
Which means you shouldn't mess with the entities during the preUpdate event handling. I suggest you move your logic up to the service layer by using an entity manager. Write a specific method for updating your entitty and do all the complex stuff there. A nice example of an entity manager would be the FOSUserBundle's UserManager
If you make a change to an entity in a preUpdate event listener you need to tell the unit of work to recompute that entity's changeset:
$em = $eventArgs->getEntityManager();
$cm = $em->getClassMetadata(get_class($entity));
$em->getUnitOfWork()->recomputeSingleEntityChangeSet($cm, $entity);