【问题标题】:symfony 3.4 : forms : allow prototype for entity 's childrensymfony 3.4:表单:允许实体的孩子原型
【发布时间】:2020-05-20 10:42:25
【问题描述】:

我的目标是创建一本书的章节,并且在每一章中,我可以有任意多的章节作为子章节。我有一个实体,它是一本书的一章 对于每一章,我可以添加一个子章(实际上是另一章(但 id parent 不为空))

class Chapter
{       
    /**
     * One champ has One parent champ.
     * @ORM\ManyToOne(targetEntity="Chapter", inversedBy="children")
     * @ORM\JoinColumn(name="id_parent", referencedColumnName="id")
     */
    public $parent; 
    
    /**
     * One champ has Many champs.
     * @ORM\OneToMany(targetEntity="Chapter", mappedBy="parent",cascade={"persist"}))
     * @ORM\OrderBy({"ordre" = "ASC"})
     */
    public $children;   

我想用 symfony 每章的形式添加/删除/修改,所以我有以下表单类型

public function buildForm(FormBuilderInterface $builder, array $options)
{
    
    $builder->add('libelleLong', textType::class, ['label'=> 'titre']);

    
     $builder->add('children', CollectionType::class,[
         'entry_type' => ChapterType::class,
         'entry_options' => ['label' => false,'block_name' => 'childrenList'],
    
         'block_name' => 'childrenList',
         'label'=> false,
         'allow_add'=>true,
         'allow_delete'=> true,
         'prototype'=> true,
         'by_reference' => false,

         ]
     );             
}

但是这条线'prototype'=> true把所有东西都放下了……

[19-May-2020 20:57:08 UTC] PHP 致命错误:允许的内存大小为 134217728 字节用尽(试图分配 32768 字节) 供应商\symfony\symfony\src\Symfony\Component\Debug\Exception\OutOfMemoryException.php 第 1 行

我怎样才能给孩子们提供原型?

【问题讨论】:

    标签: php forms symfony collections


    【解决方案1】:

    我相信,问题最终是递归。因为子表单也将有一个children 字段,其中所有子表单也将有children 字段......无限。因此,它只是为了创建它而耗尽了内存。 (这个问题只有在添加prototype 时才会出现,因为它必须渲染一个未来的孩子,它也有原型,并且必须做同样的事情 - 请注意,表单组件没有最佳地处理递归。也许你可以找到一种不同的方式在技术上和视觉上处理这个问题,例如 (pos,string,depth) 元组的列表,通过表单渲染 / js 进行光学改进,通过转换等)

    所以你必须限制这个递归的深度。一种通用的方法(我不确定这是否会起作用)是添加一个选项max_depth,它基本上告诉表单构建器是否可以进行以及可以进行多少级别。

    为此,您的表单类型类应该包含一个方法configureOptions

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setRequired(['max_depth']);
        $resolver->setDefaults([
            'data_class' => Chapter::class, // you probably have this line!
            'max_depth' => 3, // default value
        ]);
    }
    

    这将为您的表单类型添加配置选项,现在我们必须在您的buildForm 方法中使用它:

    public function buildForm(FormBuilderInterface $builder, array $options) {
    
        $builder->add('libelleLong', textType::class, ['label'=> 'titre']);
    
        // only add children sub form, if max_depth > 0, to stop infinite recursion
        if($options['max_depth'] > 0) { 
            $builder->add('children', CollectionType::class,[
                 'entry_type' => ChapterType::class,
                 'entry_options' => [
                       'label' => false,
                       'block_name' => 'childrenList',
                       // IMPORTANT!!! reduce max_depth by 1
                       'max_depth' => $options['max_depth'] - 1, 
                 ],
    
                 'block_name' => 'childrenList',
                 'label'=> false,
                 'allow_add' => true,
                 'allow_delete'=> true,
                 'prototype'=> true,
                 'by_reference' => false,
    
             ]);
        } // end if for max_depth
    }
    

    我建议将 max_depth 保持小,例如 ... 2 或 3。

    另一种方法是,创建另一种称为 SubChapterType 的表单类型,也可能是 SubSubChapterType,它基本上与 ChapterType 相同,除了它们的 childrenentry_typenext 表单类型,最后一个表单类型有 no children 字段。

    【讨论】:

    • 限制工作正常!!!非常感谢 1/ 你答案的准确性 2/ 很短的时间!!!
    猜你喜欢
    • 1970-01-01
    • 2016-06-26
    • 2014-10-20
    • 2016-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-10
    • 2015-11-01
    相关资源
    最近更新 更多