Symfony2-递归显示窗体
大家好(请原谅我的英语) 我想做一个应用程序,它需要允许用户在表单上填写他们的个人数据,他们的孩子,孙子和曾孙(一个小家谱) 在PersonType类中,我执行以下操作:Symfony2-递归显示窗体,symfony,symfony-forms,symfony-2.4,Symfony,Symfony Forms,Symfony 2.4,大家好(请原谅我的英语) 我想做一个应用程序,它需要允许用户在表单上填写他们的个人数据,他们的孩子,孙子和曾孙(一个小家谱) 在PersonType类中,我执行以下操作: class PersonType extends AbstractType { /** * @param FormBuilderInterface $builder * @param array $options */ public function buildForm(FormBuilderInterface $bui
class PersonType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('firstname');
$builder->add('lastname');
$builder->add('dateOfBirth');
$builder->add('children', 'collection', array(
'type' => new PersonType(),
'allow_add' => true,
'by_reference' => false,)
);
}
/**
* @param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Anything\YourBundle\Entity\Person'
));
}
/**
* @return string
*/
public function getName()
{
return 'person';
}
}
这样,我在控制器中使用PersonType,如下所示:
public function newAction()
{
$entity = new Person();
$form = $this->createForm(new PersonType(), $entity, array(
'action' => $this->generateUrl('person_create'),
'method' => 'POST',
));
return array(
'entity' => $entity,
'form' => $form->createView(),
);
}
但问题是,当我请求这个动作的url时,这个动作的视图必须被呈现,这是一个问题,因为它没有给出响应,因为它处于一个无限循环中(我认为这就是原因)。我想知道这是否可以使用Symfony表单实现,或者我是否需要考虑其他替代方案。如果这是可能的,我怎么能做到这一点,我怎么能限制表格只呈现我需要的四个层次(我、我的孩子、我的孙子和我的曾孙)
我希望这个问题已被理解
提前感谢。您可以在表单中添加一个自定义参数,指示当前递归级别。 要对此进行归档,您首先需要实施一个新选项:
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Anything\YourBundle\Entity\Person',
'recursionLevel' => 4
));
}
现在,在buildForm
方法中更新此值:
public function buildForm(FormBuilderInterface $builder, array $options)
{
// ...
if (--$options['recursionLevel'] > 0) {
$resolver = new OptionsResolver();
$resolver->setDefaults(
$options
);
$childType = new PersonType();
$childType->setDefaultOptions($resolver);
$builder->add('children', 'collection', array(
'type' => $childType,
'allow_add' => true,
'by_reference' => false
));
}
}
这是未经测试的。谢谢您的回答,费迪纳特 我没有按照你提出的方法解决问题,但这种方法帮助了我。我在Person窗体的构造函数中通过了递归级别,因此,我可以知道何时必须停止:
class PersonType extends AbstractType
{
private $recursionLevel;
public function __construct( $recursionLevel ){
$this->recursionLevel = $recursionLevel;
}
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
if($this->recursionLevel > 0)
{
$builder->add('children', 'collection', array(
'type' => new PersonType(--$this->recursionLevel),
'allow_add' => true,
'by_reference' => false,)
);
}
}
}
费迪纳托,谢谢你的回答。我想根据你的决定提出我的决定: public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => 'Anything\YourBundle\Entity\Person', 'recursionLevel' => 4 )); } public function buildForm(FormBuilderInterface $builder, array $options) { // ... if (--$options['recursionLevel'] > 0) { $builder->add('children', 'collection', array( 'type' => $childType, 'allow_add' => true, 'by_reference' => false, 'options' => [ 'recursionLevel' => $options['recursionLevel'] ], )); } } 公共函数setDefaultOptions(选项ResolvePrinterface$resolver) { $resolver->setDefaults(数组( 'data\u class'=>'Anything\YourBundle\Entity\Person', “递归级别”=>4 )); } 公共函数buildForm(FormBuilderInterface$builder、array$options) { // ... 如果(--$options['recursionLevel']>0){ $builder->add('children','collection',数组( 'type'=>$childType, “允许添加”=>true, “按引用”=>false, “选项”=>[ 'recursionLevel'=>$options['recursionLevel'] ], )); } }
它解决了我们的问题。我也遇到了同样的问题,并尝试了这里提供的解决方案。 它们有一些明显的缺点,比如深度限制和性能开销——即使没有提交数据,也总是创建表单对象 为了克服这个问题,我为FormEvents::PRE_SUBMIT事件添加了一个侦听器,并在有数据需要解析时动态添加collection type字段
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('content');
$builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
$node = $event->getData();
$form = $event->getForm();
if (!$node) {
return;
}
if(sizeof(@$node['children'])){
$form->add('children', CollectionType::class,
array(
'entry_type' => NodeType::class,
'allow_add' => true,
'allow_delete' => true
));
}
});
}
我希望这有助于将来出现此问题的人您的解决方案有一个缺点:因为您使用
构造函数
传递您的值,所以您无法传递。这是真的。我没有意识到这个观点。我打算改变它。感谢您的评论,费迪纳特!!
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('content');
$builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
$node = $event->getData();
$form = $event->getForm();
if (!$node) {
return;
}
if(sizeof(@$node['children'])){
$form->add('children', CollectionType::class,
array(
'entry_type' => NodeType::class,
'allow_add' => true,
'allow_delete' => true
));
}
});
}