2016-08-10 2 views
1

У меня есть событие жизненного цикла. Как только создается заказ, событие жизненного цикла prePersist добавляет несколько деталей в заказ до того, как он будет сохранен в базе данных.Вызов службы внутри события жизненного цикла

Это мой класс событий prePersist;

<?php 

namespace Qi\Bss\BaseBundle\Lib\PurchaseModule; 

use Qi\Bss\BaseBundle\Entity\Business\PmodOrder; 
use Doctrine\ORM\Event\LifecycleEventArgs; 

/** 
* Listener class 
* Handles events related to list prices 
*/ 
class OrderUserListener 
{ 

    /** 
    * Service container 
    * @var type 
    */ 
    private $serviceContainer; 

    /** 
    * Performs tasks before destruction 
    * @ORM\PrePersist 
    */ 
    public function prePersist(LifecycleEventArgs $args) 
    { 
     $order = $args->getEntity(); 

     if ($order instanceof PmodOrder) { 
      $user = $this->serviceContainer->get('security.token_storage')->getToken()->getUser(); 

      if ($user) { 
       $order->setCreatedBy($user); 
       $order->setCreatedAt(new \DateTime(date('Y-m-d H:i:s'))); 
       $order->setDepartment($user->getDepartment()); 
       $order->setStatus(PmodOrder::STATUS_AWAITING_APPROVAL); 

       $this->serviceContainer->get('bss.pmod.order_logger')->log($order, 'Order Created'); 
      } 
     } 
    } 

    /** 
    * Sets the sales order exporter object 
    * @param type $serviceContainer 
    */ 
    public function setServiceContainer($serviceContainer) 
    { 
     $this->serviceContainer = $serviceContainer; 
    } 
} 

Он отлично работает, но эта часть $this->serviceContainer->get('bss.pmod.order_logger')->log($order, 'Order Created'); не хочет работать. Я пытаюсь вызвать сервис внутри него. Я знаю, что сервис отлично работает внутри моих контроллеров, но здесь я получаю сообщение об ошибке;

Новый объект был найден через отношения 'Qi \ Bss \ BaseBundle \ Entity \ Business \ PmodLog # порядка', который не был настроен на каскада сохраняются операции для лица: Nuwe Test ВИР регистратор. Чтобы решить эту проблему: либо явно вызовите EntityManager # persist() на этом неизвестном объекте, либо сконфигурируйте каскад , сохраняйте эту ассоциацию в сопоставлении, например @ManyToOne (.., cascade = {"persist"}).

Так выглядит класс обслуживания OrderLogger;

<?php 

namespace Qi\Bss\BaseBundle\Lib\PurchaseModule; 

use Symfony\Component\HttpFoundation\Request; 
use Symfony\Component\Security\Core\Authorization\AuthorizationChecker; 
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage; 
use Doctrine\ORM\EntityManager; 
use Qi\Bss\BaseBundle\Entity\Business\PmodLog; 

/** 
* Class AppLogger. Purchase Module logger. 
* @package FcConnectBundle\Lib 
*/ 
class OrderLogger { 

    private $em; 
    private $tokenStorage; 

    /** 
    * Constructor. 
    * 
    * @param EntityManager $em 
    * @param TokenStorage $securityTokenStorage 
    */ 
    public function __construct(EntityManager $em, TokenStorage $securityTokenStorage) 
    { 
     $this->em = $em; 
     $this->tokenStorage = $securityTokenStorage; 
    } 

    /** 
    * Log an order action. 
    * 
    * @param string $text 
    */ 
    public function log($order, $action) 
    { 
     $logRecord = new PmodLog(); 
     if (is_object($this->tokenStorage->getToken())) { 
      $user = $this->tokenStorage->getToken()->getUser(); 
      if (is_object($user)) { 
       $logRecord->setUser($user); 
      } 
     } 
     $logRecord->setOrder($order); 
     $logRecord->setAction($action); 
     $logRecord->setTime(new \DateTime()); 

     $this->em->persist($logRecord); 
     $this->em->flush(); 
    } 

} 

Я уже пытался изменить сохранение в моем журнале для слияния, но это также не работает. Может ли кто-нибудь помочь и объяснить, что я делаю неправильно?

+0

Ваш сервис не должен вызывать '' $ em-> flush() '' в событии prePersist. – Alsatian

+0

Не уверен, но попробуйте передать '' $ args-> getEntityManager() '' методу журнала вместо инъекции конструктора для EntityManager. – Alsatian

+0

@Alsatian Я не понимаю 100%, мне нужно удалить флеш из моего сервиса? Но тогда он не будет работать в моих контроллерах, где я называю тот же сервис. Мне нужно это в контроллере и в моем событии prePersist. –

ответ

0

Я установил проблема, добавив postPersist и вызовите регистратор там, а не внутри моего prePersist;

/** 
* Performs tasks before destruction 
* @ORM\PostPersist 
*/ 
public function postPersist(LifecycleEventArgs $args) 
{ 
    $order = $args->getEntity(); 

    if ($order instanceof PmodOrder) {     
     $this->serviceContainer->get('bss.pmod.order_logger')->log($order, 'Order Created'); 
    } 
} 

Потому что я думаю, что происходит в том, что регистратор пытается быть выполнены, но порядок в регистраторе делает еще не существует, поскольку это еще не сохраняется. Этот способ имеет больше смысла для меня, и я думаю, что это самое простое решение. Я мог ошибаться, но любые комментарии и другие мнения по моему ответу приветствуются.

0

Это не лучшая архитектура, но он будет работать:

На prePersist добавить все сообщения в какой-то частной переменной (например, $ logMessages), и добавить еще одно событие

/** 
* @param PostFlushEventArgs $args 
*/ 
public function postFlush(PostFlushEventArgs $args) 
{ 
    $logMessages = $this->logMessages; 

    $this->logMessages = array(); //clean to avoid double logging 

    if (!empty($logMessages)) { 
     foreach ($logMessages as $message) { 
      $this->serviceContainer->get('bss.pmod.order_logger')->log($message); 
     } 

    } 
} 
Смежные вопросы