根据标题,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;
}
}
答案 0 :(得分:29)
您需要什么才能访问服务容器?
您可以使用依赖注入将任何服务注入您的侦听器(当您将侦听器定义为服务时,对吧?)。
您应该可以执行以下操作:
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注入服务容器,但是最好只注入你需要的东西,因为我认为容器知道的一切都会让你有点懒。
答案 1 :(得分: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));
在我的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
}
在我的表格订阅者
中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
}
}
}
希望它有所帮助。