[英]Form with self-referencing data (Symfony 5)
I'm doing an app with Symfony 5 and there is a problem i don't manage to find a solution, I have no idea.我正在使用 Symfony 5 做一个应用程序,并且有一个问题我无法找到解决方案,我不知道。
I want to make a form of an entity "Person".我想制作一个实体“人”的形式。 A Person can add in his family other Person.一个人可以在他的家庭中添加其他人。
So in my entity I made a Many-To-Many self referencing to Person.因此,在我的实体中,我对 Person 进行了多对多自引用。
class Person
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=50)
*/
private $name;
/**
* @ORM\Column(type="string", length=50)
*/
private $firstname;
/**
* @ORM\Column(type="string", length=255)
*/
private $birthdaydate;
/**
* @ORM\Column(type="string", length=255)
*/
private $gender;
/**
* @ManyToMany(targetEntity="Person")
* @JoinTable(name="family",
* joinColumns={@JoinColumn(name="person__id", referencedColumnName="person__id")},
* inverseJoinColumns={@JoinColumn(name="family_id", referencedColumnName="person__id")}
* )
*/
private $myFamily;
And now, I want to make a form in which I can add new Person, in a person.现在,我想制作一个表单,在其中我可以在一个人中添加新的人。 I did a CollectionType, like symfony said, but when i want to print it to the page, I get a timeout because of an infinite loop.我做了一个 CollectionType,就像 symfony 说的那样,但是当我想将它打印到页面时,由于无限循环,我得到了超时。
It's the "allow_add" which causes the problem.这是导致问题的“allow_add”。
And i need the prototype variable returned by "allow_add" to add new field in the front.我需要“allow_add”返回的原型变量在前面添加新字段。
class PersonType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('name', TextType::class, ['attr' => ['class' => 'form_textfield']])
->add('firstname')
->add('birthdayDate', TextType::class, ['attr' => ['class' => 'form_datetime']])
->add('gender', GenderType::class)
->add('submit', SubmitType::class)
->add('myFamily', CollectionType::class, array('entry_type' => PersonType::class, 'mapped' => false, 'allow_add' => true, 'by_reference' => false, 'allow_delete' => true));
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Person::class,
]);
}
}
Here is my form, but there is nothing interesting, I will add the js necessary when i will be resolve this problem.这是我的表格,但没有什么有趣的,我会在解决这个问题时添加必要的js。
{% extends 'base.html.twig' %}
{% block title %}Hello PersonController!
{% endblock %}
{% block body %}
{{ form_start(form) }}
{{ form_row(form.name) }}
{{ form_row(form.firstname) }}
{{ form_row(form.birthdayDate) }}
{{ form_row(form.gender) }}
{{ form_row(form.myFamily) }}
<button type="button" class="add_item_link" data-collection-holder-class="tags">Add a tag</but
{{ form_end(form) }}
{% endblock %}
Thanks everyone in advance.提前感谢大家。
There is an infinite loop because the myFamily property references a Person entity which itself references a myFamily property...存在一个无限循环,因为 myFamily 属性引用了一个 Person 实体,该实体本身引用了一个 myFamily 属性...
To keep things simple, one way to manage the family of a person would be to create a separate Family entity.为简单起见,管理一个人的家庭的一种方法是创建一个单独的家庭实体。 From the Person point of view, it seems more coherent to have a ManyToOne relationship with a family.从 Person 的角度来看,与家庭建立 ManyToOne 关系似乎更加连贯。 After that, you can add the family of a Person by using the EntityType:class inside the PersonFormType.之后,您可以使用 PersonFormType 中的 EntityType:class 添加 Person 的族。
Here is the documentation for EntityType: https://symfony.com/doc/current/reference/forms/types/entity.html这是 EntityType 的文档: https://symfony.com/doc/current/reference/forms/types/entity.html
The answer from Dylan Kas was good, just by adding a new form, it's good. Dylan Kas 的回答很好,只是添加了一个新的表格,就很好了。
The Person Form人员表格
class PersonType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('name', TextType::class, ['attr' => ['class' => 'form_textfield']])
->add('firstname')
->add('birthdayDate', TextType::class, ['attr' => ['class' => 'form_datetime']])
->add('gender', GenderType::class)
->add('submit', SubmitType::class)
->add('myFamily', CollectionType::class, array('entry_type' => ChildType::class, 'by_reference' => false, 'allow_add' => true, 'allow_delete' => true));
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Person::class,
]);
}
}
The child, referenced by myFamily: myFamily 引用的孩子:
class ChildType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('name', TextType::class, ['attr' => ['class' => 'form_textfield']])
->add('firstname')
->add('birthdayDate', TextType::class, ['attr' => ['class' => 'form_datetime']])
->add('gender', GenderType::class)
->add('submit', SubmitType::class);
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Person::class,
]);
}
}
And the view:和观点:
{% block body %}
{{ form_start(form) }}
{{ form_row(form.name) }}
{{ form_row(form.firstname) }}
{{ form_row(form.birthdayDate) }}
{{ form_row(form.gender) }}
<button type="button" class="add_item_link" data-collection-holder-class="myFamily">Add a tag</button>
<ul class="myFamily" data-index="{{ form.myFamily|length > 0 ? form.myFamily|last.vars.name + 1 : 0 }}" data-prototype="{{ form_widget(form.myFamily.vars.prototype)|e('html_attr') }}"></ul>
{{ form_end(form) }}
{% endblock %}
With the js associated与相关的js
const addFormToCollection = (e) => {
const collectionHolder = document.querySelector(
"." + e.currentTarget.dataset.collectionHolderClass
);
const item = document.createElement("li");
item.innerHTML = collectionHolder.dataset.prototype.replace(
/__name__/g,
collectionHolder.dataset.index
);
collectionHolder.appendChild(item);
collectionHolder.dataset.index++;
};
document
.querySelectorAll(".add_item_link")
.forEach((btn) => btn.addEventListener("click", addFormToCollection));
It still need some work, maybe I can make the child form extending the person form.它仍然需要一些工作,也许我可以让子表单扩展人表单。 The front need some work too.前线也需要一些工作。 But the next people facing this problem will have the solution here.但是下一个面临这个问题的人将在这里找到解决方案。
I am still asking myself how could I do if I've needed to have a form including itself the same form, including itself the same form etc... The form would be recursivable.我仍然在问自己,如果我需要一个包含自身相同形式的表单,包括其自身相同的表单等,我该怎么办......该表单将是可递归的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.