Reputation: 14992
Doctrine2 documentation on preUpdate
event says
This event has a powerful feature however, it is executed with a
PreUpdateEventArgs
instance, which contains a reference to the computed change-set of this entity. This means you have access to all the fields that have changed for this entity with their old and new value.
Sounds useful! So what I do:
/**
* Acme\TestBundle\Entity\Article
*
* @ORM\Entity
* @ORM\HasLifecycleCallbacks
*/
class Article
{
// ...
/**
* @ORM\PreUpdate
*/
public function preUpdate(\Doctrine\ORM\Event\PreUpdateEventArgs $eventArgs)
{
if ( /* use $eventArgs here */ )
$this->updatedAt = new \DateTime();
}
// ...
}
But no luck - no arguments are passed:
Catchable Fatal Error: Argument 1 passed to
Acme\TestBundle\Entity\Article::preUpdate()
must be an instance of
Doctrine\ORM\Event\PreUpdateEventArgs
, none given, called in
...\vendor\doctrine\lib\Doctrine\ORM\Mapping\ClassMetadataInfo.php
on line 1540 and defined in...\src\Acme\TestBundle\Entity\Article.php
line 163
I guess this must work some other way in Symfony2. How do I do it?
Upvotes: 4
Views: 9494
Reputation: 349
You should remember what with PreUpdateEventArgs instance you have access to all the fields that have CHANGED for this entity with their old and new value. But in you example updatedAt will not be at that changeset. If you try to set updatedAt value, you should get error: "Field 'updatedAt' is not a valid field of the entity". So, you can change updateAt field and then use UnitOfWork:recomputeSingleEntityChangeSet. Example:
public function preUpdate(PreUpdateEventArgs $args)
{
$entity = $args->getEntity();
$em = $args->getEntityManager();
$uow = $em->getUnitOfWork();
if ($entity instanceof Product)
{
$entity->setDiscount(123);
$uow->recomputeSingleEntityChangeSet(
$em->getClassMetadata("XXXBundle:Product"),
$entity
);
}
}
More code examples in my blog post (on russain:)): Update doctine entity in preUpdate event
Upvotes: 17
Reputation: 15087
There are two ways of handling lifecycle events.
First is simply annotate a method of your doctrine entity as @ORM\PreUpdate. This method will be called before update. The second is more complicated. It involves listener
preUpdate
. It's a separate class that you subscribe to listen to particular events.
Read carefully from here again and the symfony cookbook.
Upvotes: 4