在表单侦听器中修改查询构建器
Modify query builder in a Form listener
我创建了这样的自定义类型:
private $selectedCountryId = 0;
public function configureOptions(OptionsResolver $resolver)
{
$queryBuilder = function (CountryRepository $er) {
return $er->createQueryBuilder('c')
->where('c.active = 1')
->orWhere('c.id = :sid')
->orderBy('c.ord', 'ASC')
->addOrderBy('c.name', 'ASC')
->setParameter('sid', $this->selectedCountryId)
;
};
$resolver->setDefaults(array(
'query_builder' => $queryBuilder,
'class' => Country::class,
));
}
public function getParent()
{
return EntityType::class;
}
public function getBlockPrefix()
{
return 'CountryType';
}
我想做的是根据实体的实例修改 selectedCountryId 参数:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->addEventListener(
FormEvents::PRE_SET_DATA, array($this, 'onPreSetData')
);
}
public function onPreSetData(FormEvent $event)
{
if ($event->getData() instanceof Country) {
$this->selectedCountryId = $event->getData()->getId();
}
}
但是在这个阶段已经调用了setOptions,我不知道如何在这里修改查询生成器。
一般来说,我想要实现的是允许下拉列表中的给定国家,如果它已经针对给定实体存储(并在稍后停用)。
在这种情况下,您仍有机会在 PRE_SET_DATA
事件中修改查询构建器,因为选择列表在创建表单视图之前不会构建。
这应该可以解决问题:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
if (null !== $country = $event->getData()) {
// at this point the option is already resolved
// so it'll return the QueryBuilder instance
$qb = $event->getForm()->getConfig()->getOption('query_builder');
$qb->orWhere('c = :country')->setParameter('country', $country);
}
});
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'class' => Country::class,
'query_builder' => function (CountryRepository $r) {
return $r->createQueryBuilder('c')
->where('c.active = 1')
->orderBy('c.ord', 'ASC')
->addOrderBy('c.name', 'ASC')
;
},
]);
}
它只适用于对象的实例。
我创建了这样的自定义类型:
private $selectedCountryId = 0;
public function configureOptions(OptionsResolver $resolver)
{
$queryBuilder = function (CountryRepository $er) {
return $er->createQueryBuilder('c')
->where('c.active = 1')
->orWhere('c.id = :sid')
->orderBy('c.ord', 'ASC')
->addOrderBy('c.name', 'ASC')
->setParameter('sid', $this->selectedCountryId)
;
};
$resolver->setDefaults(array(
'query_builder' => $queryBuilder,
'class' => Country::class,
));
}
public function getParent()
{
return EntityType::class;
}
public function getBlockPrefix()
{
return 'CountryType';
}
我想做的是根据实体的实例修改 selectedCountryId 参数:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->addEventListener(
FormEvents::PRE_SET_DATA, array($this, 'onPreSetData')
);
}
public function onPreSetData(FormEvent $event)
{
if ($event->getData() instanceof Country) {
$this->selectedCountryId = $event->getData()->getId();
}
}
但是在这个阶段已经调用了setOptions,我不知道如何在这里修改查询生成器。 一般来说,我想要实现的是允许下拉列表中的给定国家,如果它已经针对给定实体存储(并在稍后停用)。
在这种情况下,您仍有机会在 PRE_SET_DATA
事件中修改查询构建器,因为选择列表在创建表单视图之前不会构建。
这应该可以解决问题:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
if (null !== $country = $event->getData()) {
// at this point the option is already resolved
// so it'll return the QueryBuilder instance
$qb = $event->getForm()->getConfig()->getOption('query_builder');
$qb->orWhere('c = :country')->setParameter('country', $country);
}
});
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'class' => Country::class,
'query_builder' => function (CountryRepository $r) {
return $r->createQueryBuilder('c')
->where('c.active = 1')
->orderBy('c.ord', 'ASC')
->addOrderBy('c.name', 'ASC')
;
},
]);
}
它只适用于对象的实例。