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以来发生了很多变化,因此对我而言我不应该做什么。
If (isset($data['id']) && 0 < $data['id']) {
$person=$em->getRepository(Person::class)->find($data['id']);
}
If (!$person) {
Throw new \Exception('Person not found');
}
// 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()))之类的数据;但这可能不是最佳解决方案。如果我能找到更好的方法,我将更新我的答案。