У меня есть форма, которую пользователь заполнил именем. Основываясь на этом имени, я делаю AJAX-запрос к своей базе данных, чтобы узнать, существует ли кто-то с таким именем. Если он существует, я показываю полную форму с входными данными, заполненными данными из базы данных. В противном случае я показываю пустую полную форму. При отправке, если данные уже были в базе данных, я хочу их обновить, но если нет, мне нужно вставить эти данные. Вставка новых данных работает нормально.
Вот моя функция контроллера, связанная с отправкой формы:
/**
*@Route("adherent/new", name = "adherent_new")
*/
public function new(Request $request)
{
$adherent = new Adherent();
$em = $this->getDoctrine()->getManager();
$form = $this->createForm(AdherentType::class, $adherent);
$form->handleRequest($request);
$produitRepository = $em->getRepository(Produit::class);
$allProduit = $produitRepository->findAll();
if ($form->isSubmitted() && $form->isValid()){
$id = $request->request->get('id');
//if id exists then update
//otherwise create a new entry
$adherent = $form->getData();
$em->persist($adherent);
$em -> flush();
return $this->redirectToRoute('adherent_accueil');
}
return $this->render('adherent/new.html.twig', [
'form' => $form->createView(),
'produits' => $allProduit
]);
}
Есть ли способ справиться с этим с помощью Symfony? Или мне нужно сделать это вручную?
Заранее спасибо !





Вместо создания нового $adherent вы можете загрузить конкретного приверженца из своей базы данных. Вручную, как в документация, но вы можете использовать Автоматическая выборка объектов (ParamConverter), что очень чисто:
composer require sensio/framework-extra-bundle
// src/Controller/ProductController.php
use App\Entity\Product;
/**
* @Route("/product/{id}", name = "product_show")
*/
public function show(Product $product)
{
// use the Product!
// ...
}
Затем, когда вы создадите свою форму с $adherent, которая теперь является объектом с информацией из вашей базы данных: $form = $this->createForm(AdherentType::class, $adherent);
Он автоматически заполнит поля формы соответствующими данными.
Я не профессионал Symfony, но я использовал его там. Посмотрите на маршрут "/terminal/create" и "/terminal/{id}/edit", если я правильно понял, он похож на то, чего вы хотите достичь.
РЕДАКТИРОВАТЬ
Если вы установите идентификатор вашего объекта перед отправкой в базу данных, он обновит вашего приверженца, если у него нет идентификатора, он создаст новый. Я думаю, вам просто нужно добавить:
if ($id){
$adherent->setId($id);
}
РЕДАКТИРОВАТЬ
перечитывая в вашем коде $adherent = $form->getData(); вероятно, уже настроен идентификатор вашего объекта, если идентификатор находится в вашей форме. Это означает, что он уже должен работать так, как вы ожидаете (обновление приверженца, если идентификатор установлен в вашей форме, и создание приверженца, если идентификатор пуст). Если нет, можете ли вы указать код своей сущности и формы?
ок, извините. Я действительно не ответил на вашу проблему тогда. Я постараюсь обновить свой ответ чем-то более точным
Хорошо, я понимаю, что вы имеете в виду. У меня не было свойства id в классе-приверженце, потому что оно расширяет абстрактный класс суперкласса Demandeur, который имеет идентификатор. Так что в моей форме AdherentType я не поместил в нее свойство id, а добавил его напрямую в html-шаблон. Это объясняет, почему я пытаюсь получить его с помощью
$id = $request->request->get('id');
Поскольку я пытался использовать getData() и поскольку у моего объекта Adherent нет свойства id и т. д. метода setId(), я получил исключение:
Could not determine access type for property "id" in class "App\Entity\Adherent": Neither the property "id" nor one of the methods "addId()"/"removeId()", "setId()", "id()", "__set()" or "__call()" exist and have public access in class "App\Entity\Adherent".
что является правдой. До этого я пробовал добавить функцию, и все работало нормально, идентификаторы и отношения.
class AdherentType extends AbstractType
{
/**
*{@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('id', IntegerType::class)
->add('nom', TextType::class, [
'constraints' => [
new NotBlank(),
new Length(['max'=>50]),
]
])
->add('prenom', TextType::class, [
'constraints' => [
new NotBlank(),
new Length(['max'=>50]),
]
])
->add('numSocietaire', IntegerType::class, [
'constraints' => [
new NotBlank(),
new Length(['max'=>30]),
]
])
->add('anciennete', IntegerType::class, [
'required' => 'false',
])
->add('contratActif', IntegerType::class, [
'required' => 'false',
])
->add('dateNaiss', DateType::class, [
'widget' => 'single_text',
'required' => 'false',
])
->add('dateAdhes', DateType::class,[
'widget' => 'single_text',
'required' => 'false',
'empty_data' => '',
])
->add('datePremMut', DateType::class, [
'widget' => 'single_text',
'required' => 'false',
])
->add('nbBenef', IntegerType::class, [
'required' => 'false',
])
->add('nbIncidPaimt', IntegerType::class, [
'required' => 'false',
])
->add('detailContrat', DetailContratType::class)
->add('formule', EntityType::class, [
'class' => Formule::class,
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('u')
->orderBy('u.libelle', 'ASC');
},
'choice_label' => 'libelle',
'required' => 'false',
])
->add('ancienneFormule', TextType::class, [
'required' => 'false',
])
->add('resiliation', ResiliationType::class)
->add('save', SubmitType::class, ['label' => 'Créer l\'adhérent']);
}
Я только что попытался добавить форму Demandeur (суперкласс) со свойством id в моей форме приверженца, но это наследование между Adherent и Demandeur, а не отношение.
class DemandeurType extends AbstractType
{
/**
*{@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('id', IntegerType::class);
}
}
class AdherentType extends AbstractType
{
/**
*{@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('demandeur', EntityType::class, [
'class' => Demandeur::class
])
....
}
}
Я чего-то не понимаю, потому что это не работает так, как я думаю, должно...
РЕДАКТИРОВАТЬ : я добавил
parent::buildForm($builder, $options);
в моем классе приверженца у меня больше нет ошибок, но я все еще не хочу ничего обновлять, просто добавляя...
Обновлено: Мне удалось заставить это работать! Поэтому я поместил свое решение на случай, если оно когда-нибудь заинтересует кого-нибудь! Я создаю файл UpdateDemandeur.php в папке EventListener. Я поместил в него функцию preUpdate, но epty, потому что ничего не нужно было делать с таблицей Demandeur перед обновлением. Сложность была в моем контроллере. Поскольку я не отправлял никаких объектов в свои формы, когда формы были отправлены, объект, который я получил, был новым для события Symfony, если я использую функцию setId($id) из-за диспетчера сущностей. Мне пришлось использовать функцию слияния. Вот код, который я использую, и он работает.
if ($request->isMethod('POST')){
foreach($forms as $form){
$form->handleRequest($request);
if ( !$form->isSubmitted()) continue;
if ($form->isValid()){
$demandeur = $form->getData();
$id = $request->request->get($type)['id'];
if ($id > 0) {
$demandeur->setId($id);
//Need to merge the new demandeur Object filled
//with data from the form to update it in database
$dem = $em->merge($demandeur);
} else {
$em->persist($demandeur);
}
$em->flush();
return $this->redirectToRoute('demandeur_add');
}
}
}
Надеюсь, это поможет кому-то!
Спасибо за ваш ответ. Я тренируюсь с Symfony. Я начинаю с этих функций, но мне нужно сочетание двух функций, например, если оно существует, обновить, если не создать. Итак, на мой взгляд, это начинается с пустой формы, как в функции создания, но когда форма отправляется, я хочу проверить, нужно ли мне обновлять или создавать в моей базе данных.