2017-08-18 79 views
1

我正在嘗試爲事件設置後臺處理系統。我使用本教程:https://informulate.com/blog/symfony/high-performance-through-asynch-operations-using-symfony-background-processing/異步事件

我跟所有的步驟,但我有2個問題:

  • 在命令,我不知道是否給調度員的事件對象是事件實體或事件默認類。我認爲它應該是默認的類,但如果是這樣,我怎麼能從我的訂閱服務器中的Event實體獲取數據?
  • 我的訂戶似乎沒有得到這個活動。

認購人:

class QCModifiedSubscriber implements EventSubscriberInterface 
{ 
public function __construct(EntityManagerInterface $em, CorrectionReponseService $correctionReponse) 
{ 
    $this->em = $em; 
    $this->correctionReponse = $correctionReponse; 
} 

public static function getSubscribedEvents() 
{ 
    // Liste des évènements écoutés et méthodes à appeler 
    return array(
     'qc.modified' => 'calculStats' 
    ); 
} 

public function calculStats(Event $event) 
{ 
    $data = $event->getData(); 
    $QC = $this->em->getRepository(QC::class)->find($data['qcId']); 
    $this->correctionReponse->correctionReponsesOfQC($QC); 
} 

}

services.yml:

services: 
    PACES\ColleBundle\EventListener\QCModifiedSubscriber: 
     tags: 
      - { name: 'kernel.event_subscriber'} 

命令:

protected function execute(InputInterface $input, OutputInterface $output) 
{ 
    $em = $this->getContainer()->get('doctrine')->getManager(); 
    $dispatcher = new EventDispatcher(); 

    while (true) { 
     $processId = rand(0, 999999999); 
     # attempts to claim a single event, returns it if successful. may return multiple events. 
     // note: $processId is some unique id to this process, helps prevent race conditions (see below) 
     $events = $em->getRepository(Event::class)->claimEvent($processId); 

     # no events to process, so break out of loop. 
     if (count($events) === 0) { 
      break; 
     } 

     # iterate over each event to be processed, typically just 1. 
     foreach ($events as $eventEntity) { 
      $output->write("Processing id: {$eventEntity->getId()}" . PHP_EOL); 

      # create the event... 
      $event = new \Symfony\Component\EventDispatcher\Event($eventEntity); 

      try { 
       # dispatch the event! 
       $dispatcher->dispatch($eventEntity->getName(), $event); 
       # if we made it here we were successful, mark as processed 
       $eventEntity->setProcessed(1); 

      } catch (\Exception $e) { 
       $eventEntity->setError((string)$e); 
      } 

      $em->persist($eventEntity); 
      $em->flush(); 
     } 
    } 
} 

事件實體exactl y和教程中的一樣。

回答

0

由於您處於Symfony框架內並尋找kernel.event_subscriber,因此您需要使用Symfony的EventDispatcher分派事件,而不是自己創建新實例。

確保您的命令擴展ContainerAwareCommand

use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; 

class MyCommand extends ContainerAwareCommand 

和改變這一行:

$dispatcher = new EventDispatcher(); 

這樣:

$dispatcher = $this->getContainer()->get('event_dispatcher'); 

要回答另一個問題,你有,事件對象給調度員的是Event類,而不是你的Event實體。你有什麼也不會在那裏工作;如果你看,Event類不接受任何構造函數參數。 Symfony's documentation states:

如果您不需要將任何其他數據傳遞給事件偵聽器,那麼也可以使用默認的Event類。在這種情況下,您可以在通用StoreEvents類中記錄事件及其名稱,類似於KernelEvents類。

你應該做的是創建特定的事件,您的活動實體,像這樣:

namespace AppBundle\Event; 

use Symfony\Component\EventDispatcher\Event; 
use AppBundle\Entity\Event as EventEntity; 

class EntityEvent extends Event 
{ 
    const NAME = 'entity.event'; 

    /** 
    * @var EventEntity 
    */ 
    protected $eventEntity; 

    public function __construct(EventEntity $eventEntity) 
    { 
     $this->eventEntity = $eventEntity; 
    } 

    public function getEventEntity() 
    { 
     return $this->eventEntity; 
    } 
} 

現在,您將創建並分派您的事件是這樣的:

use AppBundle\Event\EntityEvent; 

// ... 

$event = new EntityEvent($eventEntity); 

// ... 

$dispatcher->dispatch(EntityEvent::NAME, $event); 

然後當您訂閱活動時,您可以通過$event->getEventEntity();獲得活動實體,並按照您通常的方式在該活動上進行操作。

+0

非常感謝您的詳細解答。它現在工作完美! –

+0

很高興你的工作!這個文檔第一次讓我失望了,而且我沒有意識到從頭開始創建一個新的'EventDispatcher'就像更多的獨立工作一樣。 –