【问题标题】:Can Symfony2 form event listener access the service container and how?Symfony2 表单事件监听器可以访问服务容器吗?如何访问?
【发布时间】:2012-05-18 14:16:05
【问题描述】:

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

}

【问题讨论】:

    标签: symfony


    【解决方案1】:

    你需要访问服务容器做什么?

    您可以使用依赖注入将任何服务注入您的侦听器(因为您将侦听器定义为服务,对吗?)。

    您应该能够执行以下操作:

        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 注入服务容器,但最好只注入你需要的东西,因为我认为让容器感知所有东西会让你有点懒惰。

    【讨论】:

    • 好吧,我不知道可以将侦听器定义为服务。现在我只定义表单类型和类(作为服务)。很高兴知道!谢谢。
    • 对,所以我想这回答了你的问题?任何定义为服务的东西都可以使用依赖注入访问其他服务(包括服务容器)。
    • 那么如何获取到form中,也通过DI注入到form中?
    • 它为什么对我不起作用。你能猜出是什么原因吗?
    【解决方案2】:

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

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

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

    希望对你有帮助。

    【讨论】:

      猜你喜欢
      • 2014-06-01
      • 2016-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多