Может ли Symfony2 сформировать прослушиватель событий для доступа к контейнеру сервиса и как?
Как в заголовке, может ли прослушиватель событий формы Symfony2 обращаться к контейнеру службы?
Это пример прослушивателя событий (для события post 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;
}
}
Ответы
Ответ 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 - это идентификатор любой услуги, которую вы хотите ввести.
Если вы хотите, вы можете ввести контейнер службы с помощью @service_container, но, вероятно, лучше ввести только то, что вам нужно, потому что я думаю, что все, что знает контейнер, делает вас немного ленивым.
Ответ 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));
В моем классе 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
}
}
}
Надеюсь, что это поможет.