1

我试图在我的表单类型类中保留所有用于验证 rest api 请求的逻辑。它适用于创建新实体(POST)。

更新现有实体 (PUT) 时,验证会启动(因为我目前编写它的方式应该如此) - 但我不能在没有错误的情况下进行更新 - 任何人都对如何调整有任何经验这个:

我需要更改的是 UniqueEntity 约束,因此“拥有对象”可以更新。

class StaffType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        /*'empty_data' => 'If no value supplied, this will be the default...',*/

        $builder
        /*->add('business', EntityType::class, [
            'class' => 'App\Entity\Business',
            'invalid_message' => 'The business context is invalid.'
        ])*/
        ->add('firstName', TextType::class, [
            'constraints' => [
                new NotBlank(['message' => 'This field is missing.'])
            ]
        ])
        ->add('lastName', TextType::class, [
            'constraints' => [
                new NotBlank(['message' => 'This field is missing.'])
            ]
        ])
        ->add('email', EmailType::class, [
            'constraints' => [
                new Email(['message' => 'This value is not a valid email address.']),
            ],
        ])
        ->add('displayInCalendar', TextType::class, [
            'constraints' => [
                new Range(['min' => 0, 'max' => 1, 'notInRangeMessage' => 'This value should be between \'{{ min }}\' and \'{{ max }}\'.'])
            ]
        ]);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Staff::class,
            'csrf_protection' => false,
            'constraints' => [
                new UniqueEntity(['fields' => ['email', 'firstName', 'lastName'], 'entityClass' => 'App\Entity\Staff', 'message' => 'A user with this email, first name and last name already exists.'])
            ],
        ]);
    }

}

处理请求的控制器方法:

/**
 * @Route("/{id}", name="staff_update", methods={"PUT"}, requirements={"id"="\d+"})
 * @param Staff $staff
 * @param Request $request
 * @return JsonResponse
 */
public function update(Staff $staff, Request $request)
{
    $data = json_decode($request->getContent(), true);
    $form = $this->createForm(StaffType::class, $staff);
    $form->submit($data, false); // false: Makes partial object updates possible (PATCH)

    if ($form->isSubmitted() && $form->isValid()) {
        $this->getDoctrine()->getManager()->flush();
        return $this->apiResponse($staff, Response::HTTP_OK);
    } else {
        $errors = $this->getErrorsFromForm($form);
        return $this->apiResponse(['errors' => $errors], Response::HTTP_BAD_REQUEST);
    }
}
4

1 回答 1

0

如果与其他人相关..我通过将逻辑移动到电子邮件列的回调中以不同的方式实现它,然后在请求为 PUT 时将选项传递给表单类型类 - 然后根据那 - 似乎以良好的可读性完成这项工作。

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        /*->add('business', EntityType::class, [
            'class' => 'App\Entity\Business',
            'invalid_message' => 'The business context is invalid.'
        ])*/
        ->add('firstName', TextType::class, [
            'constraints' => [
                new NotBlank(['message' => 'This field is missing.'])
            ]
        ])
        ->add('lastName', TextType::class, [
            'constraints' => [
                new NotBlank(['message' => 'This field is missing.'])
            ]
        ])
        ->add('email', EmailType::class, [
            'constraints' => [
                new Email(['message' => 'This value is not a valid email address.']),
                new Callback(function ($email, ExecutionContextInterface $context, $payload) use ($options, $builder) {
                    $staffQueryBuilder = $this->entityManager
                        ->getRepository(Staff::class)
                        ->createQueryBuilder('q')
                        ->where('q.email = :email')
                        ->setParameter('email', $email);

                    if ($options['entity'] && $options['entity'] instanceof Staff) {
                        /** @var $staffBeingEdited Staff */
                        $staffBeingEdited = $options['entity'];
                        $staffQueryBuilder->andWhere('q.id != :id')->setParameter('id', $staffBeingEdited->getId());
                    }
                    $numberOfFoundStaff = $staffQueryBuilder->getQuery()->getResult();
                    if (count($numberOfFoundStaff) > 0) {
                        $context->addViolation('A user with this email already exists.');
                    }
                }),
            ],
        ])
        ->add('displayInCalendar', TextType::class, [
            'constraints' => [
                new Range(['min' => 0, 'max' => 1, 'notInRangeMessage' => 'This value should be between {{ min }} and {{ max }}.'])
            ]
        ]);
}
于 2020-02-02T08:16:45.877 回答