2012-05-18 23 views
12

按照標題,Symfony2表單事件偵聽器可以訪問服務容器嗎?Symfony2可以形成事件監聽器訪問服務容器,以及如何?

這是一個例子事件監聽器(用於後期綁定事件):

class CustomerTypeSubscriber implements EventSubscriberInterface 
{ 

    public static function getSubscribedEvents() 
    { 
     return array(FormEvents::POST_BIND => 'onPostBind'); 
    } 

    public function onPostBind(DataEvent $event) 
    { 
     // Get the entity (Customer type) 
     $data = $event->getData(); 

     // Get current user 
     $user = null;  

     // Remove country if address is not provided 
     if(!$data->getAddress()) : 
      $data->setCountry(null); 
     endif; 
    } 

} 

回答

28

你有什麼需要訪問服務容器?

您可以使用依賴注入將任何服務注入到您的偵聽器中(因爲您將偵聽器定義爲服務,對嗎?)。

你應該能夠做這樣的事情:

service.listener: 
    class: Path\To\Your\Class 
    calls: 
     - [ setSomeService, [@someService] ] 
    tags: 
     - { [Whatever your tags are] } 

而在你的聽衆:

private $someService; 

public function setSomeService($service) { 
    $this->someService = $someService; 
} 

哪裏someService是要注入的任何服務的ID。

如果你願意,你可以用@service_container注入服務容器,但是最好只注入你需要的東西,因爲我認爲讓所有的容器知道會讓你有點懶。

+0

那麼我不知道聽衆可以定義爲服務。現在我只定義表單類和類(作爲服務)。很高興知道!謝謝。 – gremo

+0

對,所以我想這回答你的問題?任何定義爲服務的東西都可以使用依賴注入訪問其他服務(包括服務容器)。 –

+0

如何在形式上獲得它,然後通過DI注入它以形成? – umpirsky

5

我認爲表單訂閱者的工作方式與常規事件偵聽器有點不同。

在你的控制器,你實例化表單類型,即

$form = $this->createForm(new CustomerType(), $customer); 

由於容器是在您的控制器可用,你可以直接將它傳遞給你的表單類型,即

$form = $this->createForm(new CustomerType($this->container), $customer); 

在我的情況下,我需要安全上下文,所以我的實現(類似,但與原來的q有點不同):

在我的控制器中:

$form = $this->createForm(new CustomerType($this->get('security.context')), $customer)); 

在我的窗體類:

use Symfony\Component\Security\Core\SecurityContext; 
class CustomerType extends AbstractType 
{ 
    protected $securityContext; 

    public function __construct(SecurityContext $securityContext) 
    { 
     $this->securityContext = $securityContext; 
    } 

    public function buildForm(FormBuilder $builder, array $options) 
    { 
     // Delegate responsibility for creating a particular field to EventSubscriber 
     $subscriber = new CustomerAddSpecialFieldSubscriber($builder->getFormFactory(), $this->securityContext); 
     $builder->addEventSubscriber($subscriber); 
     $builder->add(... the rest of my fields ...); 
    } 

    // other standard Form functions 
} 

在我的表格認購

use Symfony\Component\Security\Core\SecurityContext; 
CustomerAddSpecialFieldSubscriber 
{ 
    private $factory; 

    protected $securityContext; 

    public function __construct(FormFactoryInterface $factory, SecurityContext $securityContext) 
    { 
     $this->factory = $factory; 
     $this->securityContext = $securityContext; 
    } 

    public static function getSubscribedEvents() 
    { 
     return array(FormEvents::PRE_SET_DATA => 'preSetData'); 
    } 

    public function preSetData(DataEvent $event) 
    { 
     if (true === $this->securityContext->isGranted('ROLE_ADMIN')) { 
      // etc 
     } 
    } 

} 

希望它能幫助。

+0

這對我來說就像一個魅力。謝謝! –