У меня есть объект Task
с двумя обязательными полями, не допускающими обнуления:
и Форма для создания задачи.Форма вызывается внешними скриптами через 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();
}
}