Symfony 5, проверка формы - UniqueEntity при создании и обновлении выпуска / вопроса - PullRequest
0 голосов
/ 01 февраля 2020

Я пытаюсь сохранить все логи c для проверки запроса 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);
    }
}

1 Ответ

0 голосов
/ 02 февраля 2020

Если актуально для кого-то еще .. Я сделал это по-другому, переместив логи c внутри обратного вызова для столбца электронной почты, а затем передал опцию в класс типа формы, когда запрос PUT - И затем решаем лог c на основании этого - кажется, что работа с хорошей читаемостью.

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 }}.'])
            ]
        ]);
}
...