2016-02-26 106 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 –

回答