如何让服务在生命周期事件监听器中工作
How to get a service to work in a lifecycle event listener
我在项目的不同地方使用了一项服务。在我的控制器中它完美地工作。
我需要在 prePersist 生命周期事件侦听器中使用它,但无法调用那里的服务。当我尝试时,出现以下错误;
Attempted to call method "get" on class
"Xx\Xxx\XxxxBundle\Lib\Yyyy\OrderUserListener".
我想我知道我必须在我的事件侦听器中注入我的服务,但我不知道该怎么做。
OrderUserListener
和 OrderLogger
服务在 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;
}
}
如果有人可以通过展示如何使用我的示例向我解释,我将非常感激。
将$this->get('bss.pmod.order_logger')->log($order, 'Order Created');
更改为$this->serviceContainer->get('bss.pmod.order_logger')->log($order, 'Order Created');
首先,看起来您正在将 ContainerAwareInterface
(现已弃用,取而代之的是 ContainerAwareTrait
)与 Symfony 的 Controller
基础 class。 ContainerAwareInterface
旨在区分需要注入服务容器的 classes,控制器会自动注入它。由于这条线似乎有效:
$user = $this->serviceContainer->get('security.token_storage')->getToken()->getUser();
,看来容器注入正常了。
您尝试从您的服务中调用的 get()
方法实际上让我想起了 Controller
's get()
method。但是你的 class 不是 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');
}
}
我在项目的不同地方使用了一项服务。在我的控制器中它完美地工作。
我需要在 prePersist 生命周期事件侦听器中使用它,但无法调用那里的服务。当我尝试时,出现以下错误;
Attempted to call method "get" on class "Xx\Xxx\XxxxBundle\Lib\Yyyy\OrderUserListener".
我想我知道我必须在我的事件侦听器中注入我的服务,但我不知道该怎么做。
OrderUserListener
和 OrderLogger
服务在 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;
}
}
如果有人可以通过展示如何使用我的示例向我解释,我将非常感激。
将$this->get('bss.pmod.order_logger')->log($order, 'Order Created');
更改为$this->serviceContainer->get('bss.pmod.order_logger')->log($order, 'Order Created');
首先,看起来您正在将 ContainerAwareInterface
(现已弃用,取而代之的是 ContainerAwareTrait
)与 Symfony 的 Controller
基础 class。 ContainerAwareInterface
旨在区分需要注入服务容器的 classes,控制器会自动注入它。由于这条线似乎有效:
$user = $this->serviceContainer->get('security.token_storage')->getToken()->getUser();
,看来容器注入正常了。
您尝试从您的服务中调用的 get()
方法实际上让我想起了 Controller
's get()
method。但是你的 class 不是 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');
}
}