2012-05-18 11 views
12

Según el título, ¿puede un Symfony2 formador de eventos acceder al contenedor de servicios?¿Puede Symfony2 formar el receptor de eventos para acceder al contenedor de servicios y cómo?

Este es un ejemplo de detector de eventos (por evento posterior se unen):

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

} 

Respuesta

28

¿Qué se necesita para acceder al contenedor de servicios para?

Puede inyectar cualquier servicio en su oyente utilizando la inyección de dependencia (como define su oyente como un servicio, ¿verdad?).

Usted debe ser capaz de hacer algo como:

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

Y en su oyente:

private $someService; 

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

Dónde someService es el ID de cualquier servicio que desea inyectar.

Si lo desea, puede inyectar el contenedor de servicio con @service_container, pero es probable que sea mejor inyectar solo lo que necesita porque creo que tener todo lo que necesita contenedor lo hace un poco vago.

+0

Bueno, no sabía que los oyentes podrían definirse como servicio. En este momento estoy definiendo solo tipos de formularios y clases (como servicios). ¡Bueno saber! Gracias. – gremo

+0

Correcto, ¿así que supongo que eso responde a su pregunta? Todo lo que se define como un servicio puede tener acceso a otros servicios (incluido el contenedor de servicios) mediante la inyección de dependencia. –

+0

¿Cómo ponerlo en forma luego, inyectarlo para formar a través de DI también? – umpirsky

5

Creo que la forma en que funciona un Suscriptor de formulario es un poco diferente de un Oyente de evento regular.

En su controlador, se le instanciar su tipo de forma, es decir

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

Puesto que el recipiente está disponible en el controlador, se puede pasar directamente a su tipo de forma, es decir

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

En mi caso, necesitaba el contexto de seguridad, por lo que mi implementación (similar pero ligeramente diferente a su q original):

En mi controlador:

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

En mi clase 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 
} 

Y en mi Formulario de abonado

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

} 

espero que ayude.

+0

Esto funcionó para mí como un encanto. ¡Gracias! –

Cuestiones relacionadas