我的表单基于自引用实体(类别具有父类别)
对于parent
字段,我希望根据操作名称具有不同的query_builder
函数。当操作为update
时,parent
字段(下拉列表)包含除已编辑类别外的所有类别。这很好。但是,当操作为Create new
时,父窗体字段只包含null
值(在我的情况下为Main类别)。这是类别窗体类CategoryType
类:
namespace Dimas'CatalogBundle'Form;
use Symfony'Component'Form'AbstractType;
use Symfony'Component'Form'FormBuilderInterface;
use Symfony'Component'OptionsResolver'OptionsResolverInterface;
use Doctrine'ORM'EntityRepository;
class CategoryType extends AbstractType {
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('name')
->add('parent', 'entity', array(
'label' => 'Parent Category ',
'empty_value' => '- Main level -',
'class' => 'DimasCatalogBundle:Category', 'property' => 'getTreeName',
'required' => false,
'query_builder' => function(EntityRepository $er) use ($options) {
$er->createQueryBuilder('u');
//need only if action is 'update'
$er->where('u.id <> :selfId');
$er->setParameter(':selfId', $options['data']->getId());
// end if
return $er;
},
));
}
/**
* @param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver) {
$resolver->setDefaults(array(
'data_class' => 'Dimas'CatalogBundle'Entity'Category'
));
}
/**
* @return string
*/
public function getName() {
return 'dimas_catalogbundle_category';
}
}
在query_builder
中添加if
是个好主意吗?如何获取操作名称?$options
数组包含动作名称,但它的内部太深了。
将一个选项从控制器操作传递到生成器中,该操作可以作为条件:
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
if ($options['action'] === 'update') {
$callable = function (EntityRepository $er)...
} elseif ($option['action'] === 'Create new') {
$callable = function (EntityRepository $er) ...
}
...
'required' => false,
'query_builder' => $callable,
}
public function setDefaultOptions(OptionsResolverInterface $resolver) {
$resolver
->setDefaults(array(
'data_class' => 'Dimas'CatalogBundle'Entity'Category'
))
->setRequired(['action'])
;
}
// Your controller
public function createNewAction(Request $request)
{
$form = $this->createForm(new CategoryType(), $category, ['action' => 'Create new']);
}
public function updateAction(Request $request)
{
$form = $this->createForm(new CategoryType(), $category, ['action' => 'update']);
}
我通过这种方式获得结果:我在表单类中使用EventListener
。从食谱中学习现在我在CategoryType
类中的builForm
函数看起来是这样的:
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add('name');
$builder->addEventListener(FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($options) {
$category = $event->getData();
$form = $event->getForm();
// check if the Category object is "new"
// If no data is passed to the form, the data is "null".
// This should be considered a new "Category"
if (!$category || null === $category->getId()) {
$form->add('parent', 'entity', array(
'label' => 'Parent Category ',
'empty_value' => '- Main level -',
'class' => 'DimasCatalogBundle:Category', 'property' => 'getTreeName',
'required' => false,
'query_builder' => function(EntityRepository $er) use ($options) {
return $er->createQueryBuilder('u');
},
));
} else {
$form->add('parent', 'entity', array(
'label' => 'Parent Category ',
'empty_value' => '- Main level -',
'class' => 'DimasCatalogBundle:Category', 'property' => 'getTreeName',
'required' => false,
'query_builder' => function(EntityRepository $er) use ($options) {
return $er->createQueryBuilder('u')
->where('u.id <> :selfId')
->setParameter(':selfId', $options['data']->getId());
},
));
}
});
}
我没有采取行动(但我仍然没有)。