我有一个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行)中
在vendor / symfony / form / Form.php-> mapFormsToData中(第622行)
在vendor / 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();
}
}
答案 0 :(得分:0)
至少有两种方法可以解决此问题。
您必须通过两种方式将@Assert\NotNull()
添加到dueDatetime
属性。
1-您可以尝试/捕获handleRequest调用的异常。
[edit]这会中断流程,不好。
2-您可以使setter setDueDatetime(\DateTimeInterface $dueDatetime = null)
为可空值。如果选择此选项,请确保始终在DB中插入/更新之前验证您的实体,否则会出现SQL错误。
在两种情况下,它将由验证器isValid()
处理,并且您的前端会有一个不错的错误。
答案 1 :(得分:0)
您需要在方法setDueDatetime中允许可为空的参数(带有“?”)
public function setDueDatetime(?\DateTimeInterface $dueDatetime): self
{
$this->dueDatetime = $dueDatetime;
return $this;
}