为了账号安全,请及时绑定邮箱和手机立即绑定

symfony 3.4:形式:允许实体的孩子原型

symfony 3.4:形式:允许实体的孩子原型

PHP
MM们 2023-04-02 14:48:26
我的目标是创建一本书的章节,在每一章中,我可以拥有任意数量的章节作为子章节。我有一个实体,它是每一章的一本书的一章,我可以添加一个子章(实际上是另一章(但 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把一切都放下了......[2020 年 5 月 19 日 20:57:08 UTC] PHP 致命错误:供应商\symfony\symfony\src\Symfony\Component\Debug\Exception\OutOfMemoryException 中允许的 134217728 字节的内存大小已耗尽(试图分配 32768 字节)。第 1 行的 php我怎样才能让孩子们使用原型?
查看完整描述

1 回答

?
aluckdog

TA贡献1847条经验 获得超7个赞

我相信,问题最终是递归的。因为子表单也将有一个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 相同,只是它们的 是children下entry_type一个表单类型,其中最后一个表单类型没有字段 children。


查看完整回答
反对 回复 2023-04-02
  • 1 回答
  • 0 关注
  • 88 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信