2017-02-28 39 views
1

在我的應用程序中,我有「用戶」。 一個用戶可以有幾個「帳戶」EventListener更新其他實體和無限循環

我在我的「帳戶」實體上有一個監聽器。 正是在這樣的「service.yml」文件中聲明:

account_listener: 
    class: AppBundle\EventListener\AccountListener 
    arguments: 
     - '@service_container' 
    tags: 
     - {name: doctrine.event_listener, event: preUpdate} 

在我服務的方法更新前:

public function preUpdate(PreUpdateEventArgs $eventArgs) 
{ 
    $entity = $eventArgs->getEntity(); 
    if (!$entity instanceof Account) { 
     return; 
    } 

    $this->container->get('notification_manager')->sendNotification(); 
} 

的sendNotification的方法調用嘗試創建的實體的功能「的通知「

public function sendNotification() 
{ 
    $notification = new Notification(); 
    $data = array(
        'label' => 'Hello' 
       ) 
    $form_notif = $this->formFactory->create(NotificationType::class, $notification, ['method' => 'POST']); 
    $form_notif->submit($data,($method === 'POST')); 
    if ($form_notif->isValid()) 
    { 
     $this->em->persist($notification); 
     $this->em->flush(); 
    } else { 
     return $form_notif; 
    } 
    return $notification; 

} 

問題: 未創建的通知和PHP是ST在無限循環中。

爲了防止這種情況,我添加了這個在sendNotification的方法beggining:

$eventManager = $this->em->getEventManager(); 
$eventManager->removeEventListener(['preUpdate'],$this->container->get('account_listener')); 

有了這個,它的工作原理。但我認爲還有更好的辦法。

你能幫我嗎?

感謝

回答

0

如果調用該調用flush服務,我覺得removeEventListener方法是個不錯的方式,以避免無限循環。

如果你真的不想打電話給removeEventListener,你必須改變你的模式,而不是在教義事件中調用flush。

一種替代方法是使用第三個服務來收集要刷新的對象(在您的情況下,使用單個收集和少量getter/setter的NotificationStack類)。

您的sendNotification方法會將元素添加到此集合中(而不會刷新它們)。

然後,您可以沖洗kernel.response事件(和/或console.terminate,如果需要)的所有集合。

另外,在一個服務中注入容器是一個不好的實踐,你應該注入只需要的服務和或參數。

希望它會幫助

0

php卡住的原因如下。

在你的代碼調用preUpdate(),當你插入或更新的實體,稱爲....

現在,當你的sendNotification的動作會叫你保存Notification()當時事件偵聽會叫,而從事件偵聽它再次調用sendNotification方法等.....這將創建遞歸循環,這就是爲什麼ypur php卡住了。

希望它能幫助你。