John Davidson

php - Form with self-referencing data (Symfony 5)

0 comments
Message:


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.


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.


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.


It's the "allow_add" which causes the problem.


And i need the prototype variable returned by "allow_add" to add new field in the front.


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.


{% 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.



My Answer:
that references itself. For example, let's say I have an entity called "Category" and each category can have a parent category (which is also a category).

To achieve this, you can create a form type for the Category entity and use a EntityType field to reference the parent category. Here's an example of how you can do this:

1. Create a Category entity with a property for the parent category:

php
// src/Entity/Category.php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
* @ORM\Entity
*/
class Category
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;

/**
* @ORM\Column(type="string")
*/
private $name;

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

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

// Getters and setters
}


2. Create a form type for the Category entity:

php
// src/Form/CategoryType.php

namespace App\Form;

use App\Entity\Category;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;

class CategoryType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('parent', EntityType::class, [
'class' => Category::class,
'choice_label' => 'name',
'required' => false,
]);
}

public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Category::class,
]);
}
}


3. Use the CategoryType form in your controller to create and handle the form:

php
// src/Controller/CategoryController.php

namespace App\Controller;

use App\Entity\Category;
use App\Form\CategoryType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class CategoryController extends AbstractController
{
/**
* @Route("/category/new", name="category_new")
*/
public function new(Request $request): Response
{
$category = new Category();
$form = $this->createForm(CategoryType::class, $category);

$form->handleRequest($request);

if ($form->isSubmitted() && $form->isValid()) {
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($category);
$entityManager->flush();

return $this->redirectToRoute('category_new');
}

return $this->render('category/new.html.twig', [
'form' => $form->createView(),
]);
}
}


4. Create a template to render the form:

twig
{# templates/category/new.html.twig #}

{% extends 'base.html.twig' %}

{% block body %}

Create a new category



{{ form_start(form) }}
{{ form_row(form.name) }}
{{ form_row(form.parent) }}

{{ form_end(form) }}
{% endblock %}


With this setup, you should be able to create a form for the Category entity that references itself for the parent category. You can then use this form in your controller to create new categories with parent categories.

Rate this post

4 of 5 based on 1512 votes

Comments




© 2024 Hayatsk.info - Personal Blogs Platform. All Rights Reserved.
Create blog  |  Privacy Policy  |  Terms & Conditions  |  Contact Us