Symfony | Forms | Self-referencing CollectionType field - ERROR: out of memory

独自空忆成欢 提交于 2019-12-11 08:53:04

问题


First of all we are using Symfony 3.4.

We have a self-referencing field children on an Entity Category. So a category can have category-children and those category-children can have category-children and so on...

class Category
{
    /**
     * @ORM\Column(type="string")
     */
    private $title;

    /**
     * @ORM\OneToMany(targetEntity="AcmeBundle\Entity\Category", mappedBy="parent")
     */
    private $children;

    /**
     * @ORM\ManyToOne(targetEntity="AcmeBundle\Entity\Category", inversedBy="children")
     */
    private $parent;
}

Now we created an API and use the form functionality of Symfony to validate and create the objects & data. So for the categories we created this FormType:

class CategoryType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('title')
            ->add('children', CollectionType::class, [
                'entry_type' => CategoryType::class,
                'allow_add' => true,
                'allow_delete' => true,
                'mapped' => false,
                'by_reference' => false,
            ]);
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AcmeBundle\Entity\Category'
        ));
    }
}

This is an example of the API data array that is sent to the backend:

array(2) {
    [0]=>
    array(2) {
        ["title"]=>
        string(9) "Backlight"
        ["children"]=>
        array(3) {
            [0]=>
            array(2) {
                ["title"]=>
                string(10) "Technology"
                ["children"]=>
                array(0) {
                }
            }
            [1]=>
            array(2) {
                ["title"]=>
                string(12) "Panel mount "
                ["children"]=>
                array(0) {
                }
            }
            [2]=>
            array(2) {
                ["title"]=>
                string(11) "OEM modules"
                ["children"]=>
                array(0) {
                }
            }
        }
    }
    [1]=>
    array(2) {
        ["title"]=>
        string(13) "Ball diameter"
        ["children"]=>
        array(2) {
            [0]=>
            array(2) {
                ["title"]=>
                string(18) "No pointing device"
                ["children"]=>
                array(0) {
                }
            }
            [1]=>
            array(2) {
                ["title"]=>
                string(9) "Trackball"
                ["children"]=>
                array(0) {
                }
            }
        }
    }
}

But when we do the save and run this code we get this error:

[09-Aug-2018 14:41:13 Europe/Paris] PHP Fatal error:  Allowed memory size of 134217728 bytes exhausted (tried to allocate 20480 bytes) in /Applications/MAMP/htdocs/acme-project/vendor/symfony/symfony/src/Symfony/Component/OptionsResolver/OptionsResolver.php on line 865
[09-Aug-2018 14:41:13 Europe/Paris] PHP Fatal error:  Allowed memory size of 134217728 bytes exhausted (tried to allocate 32768 bytes) in /Applications/MAMP/htdocs/acme-project/vendor/symfony/symfony/src/Symfony/Component/Debug/Exception/OutOfMemoryException.php on line 1

Sooooo, it seems that it gets stuck in en infinite loop of creating FormTypes because he is creating and endless collection of children->children->children->... (The OptionsResolver is the parameter for the configureOptions() function in a FormType)

So my question is, is this even possible with the Form functionality? Or how should I program this? Or will I have to cut out the saving of Categories from the Symfony-Form-functionality and have to write my own recursive save-function?

I've seen other people asking the same thing and also not getting an answer: http://forum.symfony-project.org/forum/23/topic/70753.html


回答1:


I think you should use form events the same way as described here in symphony docs https://symfony.com/doc/current/form/dynamic_form_modification.html#dynamic-generation-for-submitted-forms attaching the PRE_SET_DATA event on the main form and the POST_SUBMIT event on the title field.

You will add the children field in the form modifier if and only if the data is either in your model or in the user's submitted data, thus stopping recursion.



来源:https://stackoverflow.com/questions/51767726/symfony-forms-self-referencing-collectiontype-field-error-out-of-memory

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!