我有一個Symfony項目,它使用Doctrine2作爲主要的ORM。該項目有多個相互關聯的實體。我有以下實體:Doctrine多個聽衆級聯
Order - order in the shop
Product - products in orders
Addon - addons for products
的對象是通過以下方式聯繫:
Order
|- Product
|- Product
|- Addon
|- Addon
的訂單和產品實體都有一個「狀態」 - 場。產品的狀態與訂單的狀態有關。產品和訂單的狀態可以通過幾種方式改變;他們需要彼此作出反應。
我正在考慮使用Doctrine EntityListeners來監聽實體中的更改。所以當訂單實體的狀態發生時,監聽器可以更新產品的狀態。
檢測訂單實體中的更改效果很好。但是當我想改變其產品的狀態時,我需要衝洗原則中的變化。當我在OrderListener中刷新產品的更改時,Symfony崩潰。
TL; DR:什麼是最好的方式來檢測實體的領域的變化,並根據這些變化更新其他實體。
由於提前,
沃特
services.yml
order_listener:
class: AppBundle\EntityListener\OrderListener
arguments: [ '@service_container' ]
tags:
- {name: doctrine.event_listener, event: preUpdate}
- {name: doctrine.event_listener, event: postFlush}
product_listener:
class: AppBundle\EntityListener\ProductListener
arguments: [ '@service_container' ]
tags:
- {name: doctrine.event_listener, event: preUpdate}
OrderListener
namespace AppBundle\EntityListener;
use AppBundle\Entity\Product;
use AppBundle\Entity\Order;
use Doctrine\ORM\Event\PostFlushEventArgs;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use Symfony\Component\DependencyInjection\Container;
class OrderListener {
/**
* @var Container
*/
protected $container;
/**
* @var PreUpdateEventArgs[]
*/
protected $changed = [];
/**
* OrderListener constructor.
*
* @param Container $container
*/
public function __construct(Container $container) {
$this->container = $container;
}
public function preUpdate(PreUpdateEventArgs $preUpdateEventArgs){
if(!$preUpdateEventArgs->getEntity() instanceof Order)
return;
$this->changed[] = $preUpdateEventArgs;
}
public function postFlush(PostFlushEventArgs $postFlushEventArgs){
foreach($this->changed as $preUpdateEventArgs){
/** @var Product $product */
$em = $this->container->get('doctrine')->getEntityManager();
foreach($preUpdateEventArgs->getEntity()->getProducts() as $product) {
$product->setStatus(Product::STATUS_COMPLETED);
$em->persist($product);
}
$em->flush();
}
$this->changed = [];
}
}
ProductListener
namespace AppBundle\EntityListener;
use AppBundle\Entity\Product;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use Symfony\Component\DependencyInjection\Container;
class ProductListener {
/**
* @var Container
*/
protected $container;
/**
* OrderListener constructor.
*
* @param Container $container
*/
public function __construct(Container $container) {
$this->container = $container;
}
public function preUpdate(PreUpdateEventArgs $eventArgs){
if(!$eventArgs->getEntity() instanceof Product)
return;
dump($eventArgs);
}
}
當沖洗訂單Symfony的這個錯誤死亡:
[Symfony\Component\Process\Exception\RuntimeException]
The process has been signaled with signal "11".
請將您的代碼添加到問題中,我們將能夠更好地爲您提供幫助。 –
您必須仔細閱讀Doctrine手冊的事件部分。許多限制和特殊情況。你可以做的一件事是實施「變更通知」,這將在Doctrine的聽衆之外工作。更多的代碼,但更容易推理。 http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/reference/change-tracking-policies.html#notify – Cerad
我已經爲聽衆添加了代碼。 @OscarPérez –