Symfony2能否形成事件监听器访问服务容器以及如何?

gre*_*emo 13 symfony

根据标题,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;
    }

}
Run Code Online (Sandbox Code Playgroud)

Chr*_*nel 29

您需要什么才能访问服务容器?

您可以使用依赖注入将任何服务注入到侦听器中(因为您将侦听器定义为服务,对吧?).

你应该可以这样做:

    service.listener:
    class: Path\To\Your\Class
    calls:
      - [ setSomeService, [@someService] ]
    tags:
      - { [Whatever your tags are] }
Run Code Online (Sandbox Code Playgroud)

在你的听众中:

private $someService;

public function setSomeService($service) {
    $this->someService = $someService;
}
Run Code Online (Sandbox Code Playgroud)

其中someService是您要注入的任何服务的ID.

如果你愿意,你可以使用@service_container注入服务容器,但最好只注入你需要的东西,因为我觉得容器知道的一切都让你有点懒.


小智 5

我认为表单订阅者的工作方式与常规事件监听器略有不同.

在您的控制器中,您正在实例化您的表单类型,即

$form = $this->createForm(new CustomerType(), $customer);
Run Code Online (Sandbox Code Playgroud)

由于容器在控制器中可用,您可以直接将其传递给表单类型,即

$form = $this->createForm(new CustomerType($this->container), $customer);
Run Code Online (Sandbox Code Playgroud)

在我的情况下,我需要安全上下文,所以我的实现(类似但与原始q略有不同):

在我的控制器中:

$form = $this->createForm(new CustomerType($this->get('security.context')), $customer));
Run Code Online (Sandbox Code Playgroud)

在我的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
}
Run Code Online (Sandbox Code Playgroud)

并在我的表格订阅者

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

}
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你.