如何在Symfony2中的Entity类中获取Kernel的实例


How to get the instance of Kernel in the Entity class in Symfony2

标题很好地解释了这个问题。我在Doctrine Entity类的生命周期回调中,想做一些额外的DB条目。为此,我需要获得内核的一个实例。我该怎么做?

大多数时候都需要实体中的容器/内核,这是错误的。实体不应该知道任何服务。为什么?

基本上,实体是一个表示事物的对象。实体主要用于关系数据库,但您可以随时将此实体用于其他事务(序列化它,从HTTP层安装它…)。
你希望你的实体是可单元测试的,这意味着你需要能够轻松地安装你的实体,而不需要任何东西,主要是没有任何业务逻辑。

您应该将您的逻辑移动到另一层,即将实例化您的实体的层
对于您的用例,我认为,最简单的方法是使用条令事件。

服务。yml

services:
    acme_foo.bar_listener:
        class: Acme'FooBundle'Bar'BarListener
        arguments:
            - @kernel
        tags:
            - { name: doctrine.event_listener, event: postLoad }

Acme''FooBundle''Bar''BarListener

use Symfony'Component'HttpKernel'KernelInterface;
use Doctrine'ORM'Event'LifecycleEventArgs;
use Acme'FooBundle'Entity'Bar;
class BarListener
{
    protected $kernel;
    /**
     * Constructor
     *
     * @param KernelInterface $kernel A kernel instance
     */
    public function __construct(KernelInterface $kernel)
    {
        $this->kernel = $kernel;
    }
    /**
     * On Post Load
     * This method will be trigerred once an entity gets loaded
     *
     * @param LifecycleEventArgs $args Doctrine event
     */
    public function postLoad(LifecycleEventArgs $args)
    {
        $entity = $args->getEntity();
        if (!($entity instanceof Bar)) {
            return;
        }
        $entity->setEnvironment($this->kernel->getEnvironment());
    }
}

这样,您的实体就可以保持平坦,没有依赖关系,并且可以轻松地对事件侦听器进行单元测试

  1. 如果必须使用某些服务,则不应该特别使用整个容器或内核实例
  2. 使用服务本身-始终尝试注入单个服务,而不是整个容器
  3. 你的案例看起来应该使用条令事件