Symfony 4.4中的行的动态更改属性[重复]

问题描述 投票:-1回答:2
我正在使用Symfony 4.4创建REST API。该API主要围绕使用Doctrine将数据放入数据库进行。我已经弄清楚了如何向数据库添加行,但是现在我只能更改数据了。我知道如何从数据库中读取行,并且从理论上讲,我可以通过调用属性的setter来更改字段,但是现在,我似乎正在获取数组而不是所需的实体,而且似乎更困难,我希望能够动态更改现有行的属性,从而不必在要更改的行的对象中包含

every字段,并调用every setter。

这是我的代码:

// PersonController.php /** * @IsGranted("ROLE_USER") * @Rest\Post("/addperson") * @param Request $request * @return Response */ public function addOrUpdatePerson(Request $request) { $data = json_decode($request->getContent(), true); $em = $this->getDoctrine()->getManager(); $person = new Person(); $form = $this->createForm(PersonType::class, $person); $form->submit($data); if (!$form->isSubmitted() || !$form->isValid()) { return $this->handleView($this->view($form->getErrors())); } if (isset($data['id'])) { // This person exists, change the row // What to do? } // This person is new, insert a new row $em->persist($person); $em->flush(); return $this->handleView($this->view(['status' => 'ok'], Response::HTTP_CREATED)); }

// PersonType.php
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('id', IntegerType::class, ['mapped' => false])
        ->add('inits')
        ->add('firstname')
        ->add('lastname')
        ->add('email')
        ->add('dateofbirth', DateTimeType::class, [
            'widget' => 'single_text',
            // this is actually the default format for single_text
            'format' => 'yyyy-MM-dd',
        ])
        // Some other stuff
        ->add('save', SubmitType::class);
}

public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults(array(
        'data_class' => Person::class,
        'csrf_protection' => false
    ));
}
我怀疑Person实体在这里是否相关,但如果有,请告诉我,我将尽快包含它!

作为对the other question from Symfony 2建议的回应;它似乎并不能完全解决我的问题。由于这个问题,我将函数更改为此(它不起作用,但不会引发任何错误):

public function addOrUpdatePerson(Request $request) { $data = json_decode($request->getContent(), true); $em = $this->getDoctrine()->getManager(); if (isset($data['id'])) { // This person exists $existing = $em->getRepository(Person::class)->find(['id' => $data['id']]); $this->getDoctrine()->getManager()->flush(); $form = $this->createForm(PersonType::class, $existing); $form->handleRequest($request); // this doesn't seem to do anything // $em->persist($existing); $em->flush(); return $this->handleView($this->view($existing)); } }

[我认为我仍然缺少一些信息,例如// perform some action, such as save the object to the database的操作。我还注意到自Symfony 2以来发生了很多变化,因此对我而言我不应该做什么。
php symfony doctrine symfony-forms
2个回答
0
投票
在'$ person = new Person()'之后添加:

If (isset($data['id']) && 0 < $data['id']) { $person=$em->getRepository(Person::class)->find($data['id']); } If (!$person) { Throw new \Exception('Person not found'); }


0
投票
1。)您不必直接使用json_decode。您可以改用以下代码:

// Person controller /** * @Route("/person", name="api.person.add", methods={"POST"}) * @Security("is_granted('ROLE_USER')") */ public function addPerson(Request $request) { $person = new Person(); $form = $this->createForm(PersonType::class, $person); $form->submit($request->request->all()); if (!$form->isSubmitted() || !$form->isValid()) { throw new \Exception((string) $form->getErrors(true)); } $em = $this->getDoctrine()->getManager(); $em->persist($person); $em->flush(); ... }

2。)更新实体时,您需要先加载它,然后跳过$ em-> persist($ entity);。部分。在这种情况下,我们通过path变量提供实体的ID(有多种方法可以提供它,但是这种方法很常见)。注意:我将$ id参数设置为混合参数,因为如果您使用的是UUID类型的ID,则它可以是整数或字符串。

// Person controller /** * @Route("/person/{id}", name=api.person.patch", methods={"PATCH"}) * @Security("is_granted('ROLE_USER')") */ public function patchPerson(Request $request, mixed $id) { // Load person $personRepository = $this->getDoctrine()->getRepository(Person::class); $person = $personRepository->find($id); if (!$person) { throw new \Exception('Entity not found'); } $form = $this->createForm(PersonType::class, $person); $form->submit($request->request->all()); if (!$form->isSubmitted() || !$form->isValid()) { throw new \Exception((string) $form->getErrors(true)); } $em = $this->getDoctrine()->getManager(); $em->flush(); ... }

3。)通常,我们不通过发布的数据设置ID属性(除非是必需的)。我们宁愿使用产生的价值。插入新实体时,生成时将使用其ID进行修改。样本:

<?php namespace App\Entity; use Ramsey\Uuid\Uuid; use Doctrine\ORM\Mapping as ORM; class Person { /** * @var Uuid * * @ORM\Id * @ORM\Column(type="uuid", unique=true) * @ORM\GeneratedValue(strategy="CUSTOM") * @ORM\CustomIdGenerator(class="Ramsey\Uuid\Doctrine\UuidGenerator") * @Groups({"public"}) */ protected $id; // Other entity properties ... public function getId(): ?string { return $this->id; } public function setId(string $id): self { $this->id = $id; return $this; } // Setters and getters for other entity properties ... }

4。] FormType(PersonType.php)中的实体类非常相关。在表单提交和验证之后,您可以在控制器内访问实体本身的属性,而不是直接从请求中访问已解码的有效负载数据。 Symfony的表单系统将确保输入数据有效,并且与实体模型或表单类型规范中设置的要求和约束相匹配。

// Person controller /** * @Route("/person", name="api.person.add", methods={"POST"}) * @Security("is_granted('ROLE_USER')") */ public function addPerson(Request $request) { $person = new Person(); $form = $this->createForm(PersonType::class, $person); $form->submit($request->request->all()); if (!$form->isSubmitted() || !$form->isValid()) { throw new \Exception((string) $form->getErrors(true)); } $em = $this->getDoctrine()->getManager(); $em->persist($person); $em->flush(); $id = $person->getId(); $firstName = $person->getFirstname(); $lastName = $person->getLastname(); // etc ... }

5。)如果要使用相同的方法/端点来添加和更新实体,则可以执行类似@lasouze的操作。

// Person controller /** * @Route("/person", name=api.person.add_or_update", methods={"POST", "PATCH"}) * @Security("is_granted('ROLE_USER')") */ public function patchPerson(Request $request) { $id = $request->request->get('id', null); if (!$id) { $person = new Person(); } else { // Load person $personRepository = $this->getDoctrine()->getRepository(Person::class); $person = $personRepository->find($id); if (!$person) { throw new \Exception('Entity not found'); } } $form = $this->createForm(PersonType::class, $person); $form->submit($request->request->all()); if (!$form->isSubmitted() || !$form->isValid()) { throw new \Exception((string) $form->getErrors(true)); } $em = $this->getDoctrine()->getManager(); $em->flush(); ... }

PS:$ form-> submit($ request-> request-> all());不适用于文件上传,因为$ request-> request-> all()不包含$ _FILES提供的参数。以我为例,我最终合并了$ form-> submit(array_merge($ request-> request-> all(),$ request-> files-> all()))之类的数据;但这可能不是最佳解决方案。如果我能找到更好的方法,我将更新我的答案。
© www.soinside.com 2019 - 2024. All rights reserved.