2016-02-26 80 views
0

我有一个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". 
+0

请将您的代码添加到问题中,我们将能够更好地为您提供帮助。 –

+1

您必须仔细阅读Doctrine手册的事件部分。许多限制和特殊情况。你可以做的一件事是实施“变更通知”,这将在Doctrine的听众之外工作。更多的代码,但更容易推理。 http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/reference/change-tracking-policies.html#notify – Cerad

+0

我已经为听众添加了代码。 @OscarPérez –

回答