Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Doctrine2's preUpdate missing PreUpdateEventArgs argument in Symfony2

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?

like image 827
Czechnology Avatar asked Nov 29 '22 15:11

Czechnology


1 Answers

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

like image 85
ruslanix.com Avatar answered Dec 02 '22 04:12

ruslanix.com