11

我发现这个问题“感谢”我得到的一个异常:

Catchable Fatal Error: Argument 3 passed to
Doctrine\ORM\Event\PreUpdateEventArgs::__construct() 
must be an array, null given, called in 
/.../vendor/doctrine/lib/Doctrine/ORM/UnitOfWork.php on line 804 
and defined in
/.../vendor/doctrine/lib/Doctrine/ORM/Event/PreUpdateEventArgs.php line 28

我正在做一个需要特定逻辑的项目:
order实体中的字段book被修改时,我需要更新books_order_modified_at父实体中的bookstore字段(这个字段可以让我知道书店中书籍的顺序是否改变了)。

我决定在事件侦听器中执行此操作,因为代码中有很多地方可能会改变书籍的顺序。

我没有找到从preUpdate事件更新相关实体的任何方法,因此我在侦听器类中有一个私有字段,用于告诉postUpdate事件更新相关bookstore实体。

我的问题是,当我这样做时,实体的preUpdate事件会被触发。 当我检查更改集时,它仅包含该字段,但前后具有相同的值。book
modified_at

如果有人有另一个想法如何解决这个问题 - 太好了。

如果没有 - 知道如何防止在preUpdate事件中调用刷新时触发postUpdate事件吗?

4

4 回答 4

6

实际上,这是来自学说Doctrine Issue DDC-2726的问题。通过在侦听器中的刷新之后添加对实体管理器的明确调用来解决它,因此该构造函数的第三个参数,实际上是 entityChangeSets,将被重写。

于 2014-05-15T09:07:36.207 回答
1

更新modified_at实体内部的内容并让学说处理呢?您将更改书中的 setOrder 方法以更新 BookOrder 实体,如下所示:

class Book {
    public function setOrder($order) {
        // modify book
        $this->bookOrder->updateModifiedAt();
    }
}

当然,您的 BookOrder 必须实现 modifiedAt:

class BookOrder {
    public function updateModifiedAt() {
        $this->modifiedAt = new \DateTime();
    }
}

如果您在 Datetime 中使用其他类,您当然必须更改此代码!

Doctrine 应该认识到 BookOrder 已经改变并且应该在不需要使用事件监听器的情况下更新它。

于 2012-07-07T14:11:27.277 回答
0

我可以建议你使用来自DoctrineExtensionsBundle的 Timestampable 扩展。

通过使用它,您不需要设置created_atmodified_at值。此扩展程序会自动执行此操作。甚至modified_at只能在修改特定字段时设置。见例子

我认为您正在编写类似此扩展程序的内容。所以,你不需要这样做,因为这已经完成了:)

于 2012-07-07T16:45:21.260 回答
0

我有一个类似的问题。尝试使用preupdate修改子元素导致相同的错误。最后,我的解决方案是简单地更新属于父母的孩子。不需要显式调用flush

/**
 * Update expiry dates for all runners belonging to a campaign
 *
 * @param $runners
 * @param $expiryDate
 */
private function updateCampaignRunners($runners, $expiryDate){
    foreach($runners as $runner){
        $runner->setExpiresAt($expiryDate);
        $this->getModelManager()->update($runner);
    }
}

/**
 * Post update and persist lifecycle callback
 *
 * @param Campaign $campaign
 */
private function postAction(Campaign $campaign)
{
    $runnerExpire = $this->getForm()->get("runnerExpire")->getData();
    if($runnerExpiryDate && $campaign->getRunners()){
        $this->updateCampaignRunners($campaign->getRunners(), $runnersExpiryDate);
    }
}
于 2015-07-30T11:44:54.880 回答