2012-05-18 10 views
12

Come per titolo, un listener di eventi del modulo Symfony2 può accedere al contenitore del servizio?Possibile che il listener di eventi del modulo Symfony2 acceda al contenitore del servizio e come?

Questo è un listener di eventi esempio (per post evento bind):

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; 
    } 

} 

risposta

28

Che cosa avete bisogno per accedere al contenitore dei servizi per?

È possibile iniettare qualsiasi servizio nel listener utilizzando l'iniezione di dipendenza (come si definisce l'ascoltatore come un servizio, giusto?).

Si dovrebbe essere in grado di fare qualcosa di simile:

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

E nel vostro ascoltatore:

private $someService; 

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

Dove someservice è l'ID di qualsiasi servizio che si desidera iniettare.

Se lo si desidera, è possibile iniettare il contenitore del servizio con @service_container, ma probabilmente è meglio iniettare solo ciò di cui si ha bisogno, perché penso che avere tutto il contenitore a conoscenza ti renda un po 'pigro.

+0

Beh, non sapevo che gli ascoltatori potessero essere definiti come servizi. In questo momento sto definendo solo tipi di moduli e classi (come servizi). Buono a sapersi! Grazie. – gremo

+0

Giusto, quindi immagino che risponda alla tua domanda? Qualsiasi cosa definita come servizio può avere accesso ad altri servizi (incluso il contenitore del servizio) usando l'iniezione di dipendenza. –

+0

Come ottenerlo in forma, quindi iniettarlo per formare anche tramite DI? – umpirsky

5

Penso che il modo in cui un Sottoscrittore di moduli funziona è leggermente diverso da un normale Listener di eventi.

Nel vostro controller, si sono istanziare il tipo di forma, cioè

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

Dal momento che il contenitore è disponibile nel controller, è possibile passare direttamente al vostro tipo di forma, cioè

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

Nel mio caso avevo bisogno del contesto di sicurezza, quindi la mia implementazione (simile ma leggermente diversa alla tua q originale):

Nel mio controller:

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

Nella mia classe Form:

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 
} 

E nella mia Subscriber Modulo

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 
     } 
    } 

} 

Speranza che aiuta.

+0

Questo ha funzionato per me come un fascino. Grazie! –

Problemi correlati