如果Symfony 4不存在数据,则创建

时间:2019-07-10 14:46:30

标签: doctrine symfony4

我有一个表格,用户填写了姓名。基于该名称,我在数据库上执行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处理此问题?还是我必须手动执行此操作?

谢谢!

2 个答案:

答案 0 :(得分:0)

代替创建新的$ adherent,您可以从数据库中加载特定的粘附者。像在documentation中一样手动操作,但是您可以使用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);
}

编辑

在您的代码中重新读取$ adherent = $ form-> getData();如果ID属于您的表单,则可能已经设置了对象的id。这意味着它应该已经可以按您期望的方式工作(如果在表单上设置了id,则更新粘附者;如果id为空,则创建粘附者)。如果没有,您可以输入您实体的代码和格式吗?

答案 1 :(得分:0)

好的,我明白你的意思了。我在依从类中没有id属性,因为它扩展了具有id的超类抽象类Demandeur。因此,在我的ckettendType表单中,我没有在其中添加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".

是真的。在此之前,我尝试了add函数,一切正常,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(超类)表单,但这是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);

在我的粘附类型类中,我不再有任何错误,但仍然不想更新任何内容,只需添加...

编辑:我设法使它正常工作!因此,我提出了解决方案,以防某天有人对它感兴趣! 我在EventListener文件夹中创建一个UpdateDemandeur.php文件。我将函数preUpdate放到了epty中,因为在更新之前不需要在Demandeur表上进行任何操作。 棘手的部分是在我的控制器中。因为我没有向表单发送任何对象,所以在提交表单时,如果由于实体管理器而使用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');
                }
            }
        }

希望它将对某人有所帮助!