M
M
Maxim2014-01-16 14:23:36
symfony
Maxim, 2014-01-16 14:23:36

Why can't save a new entity after preUpdate event?

Event

public function preUpdate(LifecycleEventArgs $args)
{
    $entity = $args->getEntity();

    if ($entity instanceof Order) {
        if ($args->hasChangedField('status') && $args->getNewValue('status') == 'stock') {
            $this->container->get('activity_logger')->writeLog($entity, 'purchase');
        }
}

writeLog
public function writeLog ($object, $comment)
{
        $entity = new Stock();
        $entity->setCategory($object->getIsotope()->getCategory()->getId());
        $entity->setComment($comment);
        $entity->setDate(new \DateTime('now'));
        $entity->setUser($object->getUser()->getId());
        $entity->setChange(TRUE);

        $this->em->persist($entity);
        $this->em->flush();
}

FatalErrorException: Error
: Maximum execution time of 60 seconds exceeded in vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php line 523

Answer the question

In order to leave comments, you need to log in

3 answer(s)
M
Maxim, 2014-01-16
@maxloyko

found a not very nice solution

$sql = "INSERT INTO table (field1, field2) VALUES ('foo', 'var')";
$stmt = $em->getConnection()->prepare($sql);
$stmt->bindValue('invoice', $invoiceId);
$result = $stmt->execute();

A
Alexey Krichko, 2014-03-17
@sand_alkr

I save all the entities for pushing at the preUpdate stage into an array into a class property, and pull them out and push them on postFlush.

class PurchaseListener {

    protected $notifications = array();

    public function preUpdate(LifecycleEventArgs $args) {
        $entity = $args->getEntity();
        $em = $args->getEntityManager();
        if ($entity instanceof Purchase) {
            ...
                    $notification = new Notification();
                    $notification->setUser($entity->getUser())
                        ->setText('блабла')
                        ->setType('success');
                    $this->notifications[] = $notification;
                ...
        }
    }

    public function postFlush(PostFlushEventArgs $event)
    {
        if(count($this->notifications)>0) {
            $em = $event->getEntityManager();
            foreach ($this->notifications as $thing) {
                $em->persist($thing);
            }
            $this->notifications = array();
            $em->flush();
        }
    }
}

T
tyz910, 2014-01-16
@tyz910

The point is that preUpdate is called inside flush. And inside preUpdate, flush is called again through the logger. You need to either execute "raw" sql without ORM, or manually call the changeset calculation instead of flush:

$this->em->persist($entity);
$meta = $this->em->getClassMetadata(get_class($entity));
$this->em->getUnitOfWork()->computeChangeSet($meta, $entity);

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question