问题
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