如果 Symfony 4 不存在数据则创建
Create if data doesn't exist with Symfony 4
我有一个用户填写了姓名的表格。基于这个名字,我在我的数据库上做了一个 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。手动像在非常干净的 documentation but you can use Automatically Fetching Objects (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 的专业人士,但我使用过它 there。如果我理解得很好,请查看路线“/terminal/create”和“/terminal/{id}/edit”,这似乎与您想要实现的目标相似。
编辑
如果您在发送到数据库之前设置了对象的 ID,它将更新您的追随者,如果没有 ID,它将创建一个新的。我认为您只需添加:
if($id){
$adherent->setId($id);
}
编辑
re-reading 在你的代码中 $adherent = $form->getData();如果 id 在您的表单中,则可能已经设置了对象的 id。这意味着它应该已经像您期望的那样工作了(如果在您的表单上设置了 id,则更新 adherent,如果 id 为空,则创建 adherent)。如果没有,你能把你的实体和形式的代码放在一起吗?
好的,我明白你的意思了。我在 adherent class 中没有 id 属性 因为它扩展了一个 superclass abstract class Demandeur 有这个 id。所以在我的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".
这是真的。在此之前,我尝试了添加功能,一切正常,ID 和关系。
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']);
}
我只是试图在我的附属表格中添加 ID 为 属性 的 Demandeur(超级 class)表格,但它是 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);
在我的 adherenttype class 中,我不再有任何错误,但仍然不想更新任何内容,只是添加...
编辑:我设法让它工作了!所以我提出了我的解决方案,以防有一天有人感兴趣!
我在 EventListener 文件夹中创建了一个 UpdateDemandeur.php 文件。我将函数 preUpdate 放入其中但为空,因为在更新之前不需要对 Demandeur table 执行任何操作。
棘手的部分在我的控制器中。因为我没有向我的表单发送任何对象,所以当表单被提交时,如果我因为实体管理器而使用 setId($id) 函数,我得到的对象对于 Symfony 事件来说是新的。我不得不使用合并功能。这是我正在使用的代码,它正在运行。
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');
}
}
}
希望对大家有所帮助!
我有一个用户填写了姓名的表格。基于这个名字,我在我的数据库上做了一个 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。手动像在非常干净的 documentation but you can use Automatically Fetching Objects (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 的专业人士,但我使用过它 there。如果我理解得很好,请查看路线“/terminal/create”和“/terminal/{id}/edit”,这似乎与您想要实现的目标相似。
编辑
如果您在发送到数据库之前设置了对象的 ID,它将更新您的追随者,如果没有 ID,它将创建一个新的。我认为您只需添加:
if($id){
$adherent->setId($id);
}
编辑
re-reading 在你的代码中 $adherent = $form->getData();如果 id 在您的表单中,则可能已经设置了对象的 id。这意味着它应该已经像您期望的那样工作了(如果在您的表单上设置了 id,则更新 adherent,如果 id 为空,则创建 adherent)。如果没有,你能把你的实体和形式的代码放在一起吗?
好的,我明白你的意思了。我在 adherent class 中没有 id 属性 因为它扩展了一个 superclass abstract class Demandeur 有这个 id。所以在我的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".
这是真的。在此之前,我尝试了添加功能,一切正常,ID 和关系。
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']);
}
我只是试图在我的附属表格中添加 ID 为 属性 的 Demandeur(超级 class)表格,但它是 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);
在我的 adherenttype class 中,我不再有任何错误,但仍然不想更新任何内容,只是添加...
编辑:我设法让它工作了!所以我提出了我的解决方案,以防有一天有人感兴趣! 我在 EventListener 文件夹中创建了一个 UpdateDemandeur.php 文件。我将函数 preUpdate 放入其中但为空,因为在更新之前不需要对 Demandeur table 执行任何操作。 棘手的部分在我的控制器中。因为我没有向我的表单发送任何对象,所以当表单被提交时,如果我因为实体管理器而使用 setId($id) 函数,我得到的对象对于 Symfony 事件来说是新的。我不得不使用合并功能。这是我正在使用的代码,它正在运行。
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');
}
}
}
希望对大家有所帮助!