Symfony | Forms | Self-referencing CollectionType field - ERROR: out of memory
Symfony | Forms | Self-referencing CollectionType field - ERROR: out of memory
首先我们使用 Symfony 3.4.
我们在实体 Category
上有一个 自引用字段 children
。所以一个类别可以有类别子项,那些类别子项可以有类别子项等等...
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;
}
现在我们创建了一个 API 并使用 Symfony 的 表单功能 来验证和创建对象和数据。因此,对于类别,我们创建了这个 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'
));
}
}
这是发送到后端的API数据数组的示例:
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) {
}
}
}
}
}
但是当我们保存并运行这个代码时,我们得到这个错误:
[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,它 似乎 它陷入了创建 FormTypes 的 无限循环 因为他正在创建和无穷无尽的子集 - >children->children->...(OptionsResolver
是 FormType 中 configureOptions()
函数的参数)
所以我的问题是,这甚至可以通过表单功能实现吗?或者我应该如何编程?或者我是否必须从 Symfony 表单功能中删除类别的保存并必须编写我自己的递归保存功能?
我见过 其他人 问过同样的问题但也没有得到答案:
http://forum.symfony-project.org/forum/23/topic/70753.html
我认为您应该按照 symphony 文档中描述的方式使用表单事件 https://symfony.com/doc/current/form/dynamic_form_modification.html#dynamic-generation-for-submitted-forms
在主窗体上附加 PRE_SET_DATA
事件,在 title
字段上附加 POST_SUBMIT
事件。
当且仅当数据在您的模型或用户提交的数据中时,您将在表单修饰符中添加 children
字段,从而停止递归。
首先我们使用 Symfony 3.4.
我们在实体 Category
上有一个 自引用字段 children
。所以一个类别可以有类别子项,那些类别子项可以有类别子项等等...
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;
}
现在我们创建了一个 API 并使用 Symfony 的 表单功能 来验证和创建对象和数据。因此,对于类别,我们创建了这个 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'
));
}
}
这是发送到后端的API数据数组的示例:
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) {
}
}
}
}
}
但是当我们保存并运行这个代码时,我们得到这个错误:
[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,它 似乎 它陷入了创建 FormTypes 的 无限循环 因为他正在创建和无穷无尽的子集 - >children->children->...(OptionsResolver
是 FormType 中 configureOptions()
函数的参数)
所以我的问题是,这甚至可以通过表单功能实现吗?或者我应该如何编程?或者我是否必须从 Symfony 表单功能中删除类别的保存并必须编写我自己的递归保存功能?
我见过 其他人 问过同样的问题但也没有得到答案: http://forum.symfony-project.org/forum/23/topic/70753.html
我认为您应该按照 symphony 文档中描述的方式使用表单事件 https://symfony.com/doc/current/form/dynamic_form_modification.html#dynamic-generation-for-submitted-forms
在主窗体上附加 PRE_SET_DATA
事件,在 title
字段上附加 POST_SUBMIT
事件。
当且仅当数据在您的模型或用户提交的数据中时,您将在表单修饰符中添加 children
字段,从而停止递归。