我有一个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 –