У меня есть проект Symfony 4 с формой быстрого бронирования на моей домашней странице, где я должен выбрать дату (DateType) и предложение (EntityType of Offre entity).
Когда форма отправлена и является действительной, я сериализую свой ReservationRapideModel и сохраняю его в сеансе.
Затем перенаправляю пользователя на страницу резервирования, которая снова содержит эти два поля (поэтому вновый контроллер).Я хочу предварительно заполнить их, если у меня есть ReservationRapideModel в сеансе, но у меня есть эта ошибка:
Необходимо управлять объектом типа «App \ Entity \ Offre», передаваемым в поле выбора.Может быть, вы забыли сохранить его в менеджере сущностей?
Моя сущность Offre - это справочные данные, поэтому мне не нужно регистрировать ее в моей базе данных, а только иметь внешний ключ в таблице резервирования.Его атрибутами являются только идентификатор и метка.
Моя модель для формы быстрого бронирования:
<?php
declare(strict_types = 1);
namespace App\Model;
use App\Entity\Offre;
use App\Helper\Traits\Entity\General\TraitEntityGeneralId;
use DateTime;
use Symfony\Component\Validator\Constraints as Assert;
class ReservationRapideModel
{
use TraitEntityGeneralId;
/**
* @Assert\DateTime()
* @Assert\GreaterThanOrEqual("tomorrow")
* @Assert\NotBlank()
*
* @var DateTime|null
*/
protected $dateDebut;
/**
* @var Offre|null
*/
protected $offre;
public function __construct()
{
$this->dateDebut = new DateTime('tomorrow');
}
// getters and setters here
}
И тип ее формы:
<?php
declare(strict_types = 1);
namespace App\Form;
use App\Entity\Offre;
use App\Model\ReservationRapideModel;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ReservationRapideType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('dateDebut', DateTimeType::class, [
'attr' => [
'placeholder' => 'Date et heure',
'class' => 'form-control datetimepicker-input search_form_select',
],
'widget' => 'single_text',
'format' => 'dd/MM/yyyy',
'html5' => false,
'label' => false,
])
->add('offre', EntityType::class, [
'class' => Offre::class,
'multiple' => false,
'placeholder' => 'Choix de l\'offre',
'label' => false,
'choice_label' => function (Offre $offre) {
return $offre->__toString();
},
'attr' => [
'class' => 'search_form_select',
],
])
->add('submit', SubmitType::class, [
'label' => 'Réserver',
'attr' => [
'class' => 'search_bar_button',
],
]);
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => ReservationRapideModel::class,
]
);
}
}
Первый контроллер:
<?php
declare(strict_types = 1);
namespace App\Controller;
use App\Form\ReservationRapideType;
use App\Model\ReservationRapideModel;
use App\Service\ServiceSerializer;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
/**
* @Route("/partial", name="site_partial_")
*
* @Security("is_granted('IS_AUTHENTICATED_ANONYMOUSLY')")
*/
class PartialController extends BaseController
{
/**
* @Route("/reservation-rapide", name="reservation_rapide", methods={"POST"})
*/
public function reservationRapide(Request $request, ServiceSerializer $serviceSerializer)
{
$session = $request->getSession();
$reservationRapide = new ReservationRapideModel();
if ($session !== null && $session->get('reservation_rapide') !== null) {
$string = $session->get('reservation_rapide');
$reservationRapide = $this->serviceSerializer->deserializeJson($string, ReservationRapideModel::class);
}
$form = $this->createForm(ReservationRapideType::class, $reservationRapide);
$form->handleRequest($request);
if ($form->isSubmitted() === true) {
if ($form->isValid() === true) {
$session = $request->getSession();
$string = $serviceSerializer->serializeJson($reservationRapide);
if ($session !== null) {
$session->set('reservation_rapide', $string);
}
return $this->redirectToRoute('site_reservation_index');
}
$this->addFlash('danger', 'Le formulaire comporte des erreurs.');
return $this->redirectToRoute('site_reservation_index');
}
return $this->render('site/layout/partials/reservation_rapide.html.twig', [
'form' => $form->createView(),
'reservationRapide' => $reservationRapide,
]);
}
}
Второй контроллер:
<?php
declare(strict_types = 1);
namespace App\Controller;
use App\Entity\Departement;
use App\Entity\Paiement;
use App\Entity\Planification;
use App\Entity\Prestataire;
use App\Entity\Reservation;
use App\Form\ReservationType;
use App\Model\ReservationRapideModel;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
/**
* @Route(name="site_reservation_")
*
* @Security("is_granted('IS_AUTHENTICATED_ANONYMOUSLY')")
*/
class ReservationController extends BaseController
{
/**
* @Route("/reservation", name="index", methods={"GET", "POST"})
*
* @Security("is_granted('IS_AUTHENTICATED_ANONYMOUSLY')")
*/
public function index(Request $request): Response
{
$session = $request->getSession();
$reservation = new Reservation();
if ($session !== null && $session->get('reservation_rapide') !== null) {
$string = $session->get('reservation_rapide');
$reservationRapide = $this->serviceSerializer->deserializeJson($string, ReservationRapideModel::class);
if ($reservationRapide instanceof ReservationRapideModel) {
$planification = new Planification();
$planification->setOffre($reservationRapide->getOffre());
$planification->setDateDebut($reservationRapide->getDateDebut());
$reservation->setPlanification($planification);
}
}
$formReservation = $this->createForm(ReservationType::class, $reservation);
$formReservation->handleRequest($request);
Ошибка во втором контроллере в этой строке:
$formReservation = $this->createForm(ReservationType::class, $reservation);