Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/.htaccess/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Symfony2-递归显示窗体_Symfony_Symfony Forms_Symfony 2.4 - Fatal编程技术网

Symfony2-递归显示窗体

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

大家好(请原谅我的英语)

我想做一个应用程序,它需要允许用户在表单上填写他们的个人数据,他们的孩子,孙子和曾孙(一个小家谱)

在PersonType类中,我执行以下操作:

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
                ));
        }
    });

}