2014-04-24 93 views
3

标题很好地解释了这个问题。我处于Doctrine Entity类的生命周期回调中,并想要执行一些额外的数据库条目。为此,我需要获取内核的一个实例。我怎样才能做到这一点?如何在Symfony2的实体类中获得内核的实例

+1

我认为你做错了,你不应该需要一个实体中的内核。你的用例是什么? – Touki

+0

在回调中,我需要做一些数据库操作以保持一些内部的一致性。为了完成这些数据库操作,我需要获取对象管理器的实例并获取OM(它被注册为服务)的实例,我需要内核实例。 –

+1

有**必须**是使用LifecycleCallbacks的另一种方法。一个* postLoad事件监听器*怎么样?在那里你可以很容易地给你的构造函数中的内核实例的对象管理器,而不是打破标准? – Touki

回答

6

孤男寡女在一个实体的容器/内核的大部分时间,错误。一个实体不应该知道任何服务。这是为什么?

基本上,一个实体是一个代表事物的对象。一个实体主要用在一个关系数据库中,但是你可以随时使用这个实体来处理其他事情(序列化它,从HTTP层实例化...)。
您希望您的实体可以进行单元测试,这意味着您需要能够轻松实例化您的实体,而无需任何东西,大部分都没有任何业务逻辑。

你应该将自己的逻辑转移到另一个层面,这个层面可以实现你的实体。
对于您的使用案例,我认为,最简单的方法是使用doctrine event

services.yml

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

的Acme \ FooBundle \酒吧\ 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
  1. 如果您必须使用某些服务,则不应该特别使用整个容器或内核实例。
  2. 使用的服务本身 - 总是试图注入单一的服务,而不是整个容器
  3. 你的情况看起来像你应该使用doctrine events