如何使服务在生命周期事件侦听器中工作

时间:2016-07-29 13:54:18

标签: php symfony event-listener

我有一项服务,我在项目的不同地方使用。在我的控制器中它完美无缺。

我需要在prePersist生命周期事件监听器中使用它,但在那里调用服务不想工作。当我尝试它时,我得到以下错误;

  

在课堂上尝试调用方法“get”   “XX \的xxx \ XxxxBundle \ LIB \ yyyy年\ OrderUserListener”。

我认为我明白我必须在我的事件监听器中注入我的服务,但我不明白该怎么做。

这是OrderUserListenerOrderLogger服务分别在service.yml文件中的样子;

bss.pmod.current_user_id:
    class: Xx\Xxx\XxxxBundle\Lib\Yyyy\OrderUserListener
    calls:
    - [ setServiceContainer, [@service_container] ]
    tags:
        - { name: doctrine.event_listener, event: prePersist }

bss.pmod.order_logger:
    class: Xx\Xxx\XxxxBundle\Lib\Yyyy\OrderLogger
    arguments: [ "@doctrine.orm.entity_manager", "@security.token_storage" ]

这是我想要在我的服务中注入的OrderLogger功能;

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();
    }

}

我的事件监听器看起来像这样;

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->get('bss.pmod.order_logger')->log($order, 'Order Created');      // This is then clearly wrong.
            }
        }
    }

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

如果有人可以通过展示如何使用我的样品向我解释,我会非常感激。

2 个答案:

答案 0 :(得分:1)

首先,看起来您正在使用Symfony的ContainerAwareInterface基类混合ContainerAwareTrait(现在已弃用Controller)。 ContainerAwareInterface旨在区分需要注入服务容器的类,控制器会自动注入它。由于看起来这条线有效:

$user = $this->serviceContainer->get('security.token_storage')->getToken()->getUser();

,看起来容器正确注入。

您尝试从服务中调用的get()方法实际上让我想起Controller's get() method。但是你的班级不是Controller的后代,据我所知,它实际上并不是一个控制者。

你应该做的不是在这里调用get()而是调用容器:

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

然而,ContainerAware服务通常被认为是一种不好的做法。您可以直接通过构造函数注入服务:

# Service definition
bss.pmod.current_user_id:
    class: Xx\Xxx\XxxxBundle\Lib\Yyyy\OrderUserListener
    arguments:
        - "@security.token_storage"
        - "@bss.pmod.order_logger"
    tags:
        - { name: doctrine.event_listener, event: prePersist }

class OrderUserListener
{
    private $tokenStorage;

    private $logger;

    public function __construct($tokenStorage, $logger)
    {
        $this->tokenStorage = $tokenStorage;
        $this->logger = $logger;
    }

    // ...

    public function prePersist(LifecycleEventArgs $args)
    {
        // ...

        // Here you can call the injected services:
        $user = $this->tokenStorage->getToken()->getUser();

        $this->logger->log($order, 'Created');
    }
}

答案 1 :(得分:-1)

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