Entity of type passed to the choice field must be managed. Maybe you forget to persist it in the entity manager?

Viewed 66

I made a search form where several entities are present. I would like to keep last values entered so that when user comes back to the form, he retrieves his last choices.

By trying to do so, I retrieve myself with the following error :

Entity of type "App\Entity\BigCity" passed to the choice field must be managed. Maybe you forget to persist it in the entity manager?

When I saw this error, I added the following line : $entityManagerInterface->persist($data); but I retrieve myself with an other error :

EntityManager#persist() expects parameter 1 to be an entity object, array given.

What should I do to avoid these errors ?

EventsController.php

<?php

namespace App\Controller;

use App\Form\SearchType;
use App\Repository\EventsRepository;
use App\Repository\CategoriesRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;

class EventsController extends AbstractController
{   
    private $requestStack;

    public function __construct(RequestStack $requestStack)
    {
        $this->requestStack = $requestStack;
    }

    #[Route('/search', name: 'search')]
    public function search(Request $request, EntityManagerInterface $entityManagerInterface,)
    {   
        $data = $request->query->all();
        $sessionFormData  = $sessionInterface->get('data');

        $form = $this->createForm(SearchType::class, $sessionFormData);
        $form->handleRequest($request);
        
        if ($form->isSubmitted() && $form->isValid()) {
            $data = $form->getData();
            $session->set('data', $data);
            return $this->render('front/events.html.twig', $data);
        }

        return $this->renderForm('front/search.html.twig', [
            'form' => $form
        ]);
    }

SearchType.php

<?php

namespace App\Form;

use App\Entity\BigCity;
use App\Entity\Categories;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;

class SearchType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('bigcity', EntityType::class, [
                'class' => BigCity::class,
                'choice_label' => 'name',
                'placeholder' => 'Sélectionne une grande ville'
            ])
            ->add('category', EntityType::class, [
                'class' => Categories::class,
                'choice_label' => 'image',
                'expanded' => true,
                'multiple' => false,
            ])
            ->add('save', SubmitType::class)
        ;
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'data_class' => null
        ]);
    }
}
1 Answers

if you want to save values in session you can use SessionInterface, after that you pass the sessions values in the options of createForm method

use Symfony\Component\HttpFoundation\Session\SessionInterface;

public function someAction(Request $request, SessionInterface $session)
{
   $data = $request->request->all();

   $sessionSearchFormData  = $session->get('searchFormData'); // null at the first time

   $form = $this->createForm(SearchType::class, null, ['sessionSearchFormData'=> $sessionSearchFormData]);
   $form->handleRequest($request);

    if($form->isSubmitted())
    {
        // put values of form in session just after each time the form is submitted
        $session->set('searchFormData', $data);
    }

}

use Doctrine\ORM\EntityManagerInterface;

class SearchType extends AbstractType
{
   private EntityManagerInterface $entityManager;

   public function __construct(EntityManagerInterface $entityManager)
   {
      $this->entityManager = $entityManager;
   }

   public function buildForm(FormBuilderInterface $builder, array $options): void
   {

    $bigcity = $options['sessionSearchFormData'] !== null ? $options['sessionSearchFormData']['bigcity'] : '';

    $builder
        ->add('bigcity', EntityType::class, [
            'class' => BigCity::class,
            'choice_label' => 'name',
            'placeholder' => 'Sélectionne une grande ville',
            'data'=> $bigcity !== null ? $this->entityManager->getRepository(BigCity::class)->find($bigcity) : ''
        ])
        ->add('category', EntityType::class, [
            'class' => Categories::class,
            'choice_label' => 'image',
            'expanded' => true,
            'multiple' => false,
        ])
        ->add('save', SubmitType::class)
    ;
}

public function configureOptions(OptionsResolver $resolver): void
{
    $resolver->setDefaults([
        'data_class' => null,
         'sessionSearchFormData' => null, // don't forget this
    ]);
}

EDIT:

This is another solution, you don't need to do anything in the formType nor passing any values as options, just remove $form->handleRequest and add $form->submit()

In twig

<form action="" method="post">

The controller

public function someAction(Request $request, SessionInterface $session)
{
    // $data = $request->query->all(); // if GET method
    $data = $request->request->all(); // if POST method
    
    if($request->getMethod() === 'POST') {
        $session->set('searchFormData', $data);
    }
    $sessionSearchFormData = $session->get('searchFormData');

    $form = $this->createForm(SearchType::class);
    $form->submit($sessionSearchFormData);

    return $this->renderForm('front/search.html.twig', [
        'form' => $form
    ]);
}
Related