我发现这个问题“谢谢”我得到的一个例外:
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
事件更新相关{ {1}}实体。
我的问题是,当我这样做时,bookstore
实体的preUpdate
事件被触发。
当我检查更改集时,它仅包含book
字段,但它在前后具有相同的值。
如果有人不知道如何解决问题 - 很棒。
如果没有 - 任何想法如何在teh modified_at
事件中调用flush时阻止preUpdate
事件被触发?
答案 0 :(得分:6)
实际上,这是来自学说Doctrine Issue DDC-2726的问题。通过在侦听器中刷新后在实体管理器上添加一个清除调用来解决它,因此将重写该构造函数的第3个参数,实际上是entityChangeSets。
答案 1 :(得分:1)
如何更新实体中的modified_at
并让doctrine处理它?您可以在书中更改setOrder方法,以更新BookOrder实体,如下所示:
class Book {
public function setOrder($order) {
// modify book
$this->bookOrder->updateModifiedAt();
}
}
当然,您的BookOrder必须实现modifiedAt:
class BookOrder {
public function updateModifiedAt() {
$this->modifiedAt = new \DateTime();
}
}
如果您在日期时使用其他课程,则当然必须更改此代码!
Doctrine应该认识到BookOrder已经改变,应该更新它而不需要使用事件监听器。
答案 2 :(得分:0)
我建议您使用来自DoctrineExtensionsBundle的Doctrine的Timestampable扩展名。
通过使用它,您无需设置created_at
或modified_at
值。此扩展程序自动执行。即使只有在修改特定字段时才能设置modified_at
。请参阅example。
我认为你正在写这样的扩展名。所以,你不需要这样做,因为这已经完成了:)
答案 3 :(得分: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);
}
}