Symfony4, как правильно обрабатывать недостающие поля формы?(без исключения в $ this-> propertyAccessor-> setValue) - PullRequest
0 голосов
/ 22 февраля 2019

У меня есть объект Task с двумя обязательными полями, не допускающими обнуления:

  • title
  • dueDatetime

и Форма для создания задачи.Форма вызывается внешними скриптами через POST с application/x-www-form-urlencoded (так что json или что-то необычное), поэтому я использую стандартный symfony для этого.

Проблема в том, что я не контролирую скрипты, иесли сценарий забыл один из аргументов, symfony4 напрямую сгенерирует исключение на шаге handleRequest, прежде чем у меня будет время проверить, является ли форма действительной или нет.В результате получился уродливый ответ 500.

Мой вопрос: как этого избежать?Лучшим для меня было бы просто продолжать использовать "form-> isValid ()", как и раньше, но если есть другой стандартный способ справиться с этим, это тоже хорошо.

Примечание: было бы лучше, еслиМне не нужно указывать установщик моей сущности как принимающий нулевые значения

Исключение, которое я получил:

Ожидаемый аргумент типа "DateTimeInterface", задано значение "NULL".
в vendor / symfony / property-acces /PropertyAccessor.php::throwInvalidArgumentException (строка 153)
в vendor / symfony / form / Extension / Core / DataMapper / PropertyPathMapper.php-> setValue (строка 85)
в поставщике/symfony/form/Form.php->mapFormsToData (строка 622)
в поставщике / symfony / form / Extension / HttpFoundation / HttpFoundationRequestHandler.php-> submit (строка 108)
в vendor / symfony / form / Form.php-> handleRequest (строка 492)

Завиток, воспроизводящий ошибку:

curl -d 'title=foo' http://127.0.0.1:8080/users/api/tasks

Код:

Объект:

class Task
{


    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="bigint")
     */
    private $id;

    /**
     * @Assert\NotNull()
     * @Assert\NotBlank()
     * @ORM\Column(type="string", length=500)
     */
    private $title;
    /**
     *
     * @ORM\Column(type="datetimetz")
     */
    private $dueDatetime;

    public function getDueDatetime(): ?\DateTimeInterface
    {
        return $this->dueDatetime;
    }

    public function setDueDatetime(\DateTimeInterface $dueDatetime): self
    {
        $this->dueDatetime = $dueDatetime;
        return $this;
    }

    public function setTitle($title)
    {
        $this->title = $title;
        return $this;
    }

    public function getTitle()
    {
        return $this->title;
    }

}

Форма

class TaskType extends AbstractType                                                                                     
{                                                                                                                       
    public function buildForm(FormBuilderInterface $builder, array $options)                                            
    {                                                                                                                   
        $builder                                                  
            ->add('title')                                                                                                                                                   
            ->add('dueDatetime')
        ;
    }
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(['data_class' => Task::class]);
    }
}

Контроллер:

class TaskController extends AbstractController
{
   /**
     * @Route(
     *   "/users/api/tasks",
     *   methods={"POST"},
     *   name="user_api_create_task"
     * )
     */
    public function apiCreateTask(Request $request)
    {
        $task = new Task();;

        // the use of createNamed with an empty string is just so that
        // the external scripts don't have to know about symfony's convention
        $formFactory = $this->container->get('form.factory');
        $form = $formFactory->createNamed(
            '',
            TaskType::class,
            $task
        );
        $form->handleRequest($request); // <-- this throw exception

        // but this code should handle this no ? 
        if (!$form->isSubmitted() || !$form->isValid()) {
            return new JsonResponse([], 422);
        }
        $entityManager = $this->getDoctrine()->getManager();
        $entityManager->persist($task);
        $entityManager->flush();


        return new JsonResponse();
    }
}

1 Ответ

0 голосов
/ 22 февраля 2019

Есть как минимум 2 способа справиться с этим.Двумя способами вам придется добавить @Assert\NotNull() к атрибуту dueDatetime.

1 - вы можете попытаться / поймать исключение вызова handleRequest.
[edit] это нарушает поток, а не хорошо.

2 - Вы можете сделать установщик обнуляемым setDueDatetime(\DateTimeInterface $dueDatetime = null).Если вы выберете этот вариант, всегда проверяйте свою сущность перед вставкой / обновлением в БД, иначе вы получите ошибку SQL.

В обоих случаях она будет обработана валидатором isValid() иу вас будет приятная ошибка в вашем интерфейсе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...