2014-04-24 179 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