[英]How to properly do a REST API POST call using FOSRest and Symfony 3.0
对于我当前正在构建的API,我希望能够发送带有以下内容的JSON正文的请求
{"title": "foo"}
为名为Project
的实体创建新的数据库记录。
我做了一个子类FOSRestController
的控制器。 为了创建一个项目,我做了一个动作
/**
* @Route("/")
*
* @ApiDoc(
* section="Project",
* resource=true,
* input={"class"="AppBundle\Form\API\ProjectType"},
* description="Creates a new project",
* statusCodes={
* 201="Returned when successful",
* }
* )
*
* @Method("POST")
* @Rest\View(statusCode=201)
*/
public function createProjectAction(Request $request)
{
$project = new Project();
$form = $this->createForm(ProjectType::class, $project);
$form->submit(($request->request->get($form->getName())));
if ($form->isSubmitted() && $form->isValid()) {
return $project;
}
return View::create($form, 400);
}
ProjectType
看起来像这样
class ProjectType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('title');
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Project'
));
}
}
但是,当我尝试将上述JSON发布到API时,它会响应title
属性不能为空,这很好,因为这是为其设置的验证规则。 但是,它已设置。 我突然意识到我必须发送以实际对象名称为前缀的JSON才能完成此工作:
{"project":{"title": "bla"}}
公平地说,这有点奇怪,仅发布属性就足够了。
因此,基于此信息,我仅有两个问题:
($request->request->get($form->getName()))
“提交”此表单,所以$request
不够吗? 编辑1:在“默认选项”中添加或删除data_class
根本不会更改行为。
这是因为Symfony Controller“ createForm”帮助器方法的工作方式。 其背后的原因是多种形式可能具有相同的目标URL。 通过以表单名称作为前缀,Symfony可以知道提交的表单。
通过查看“ createForm”方法的实现可以看出:
public function createForm($type, $data = null, array $options = array())
{
return $this->container->get('form.factory')->create($type, $data, $options);
}
如果您不希望出现这种情况,则更改它确实很容易:
public function createProjectAction(Request $request)
{
$project = new Project();
$form = $this->get('form.factory')->createNamed(null, new ProjectType(), $project);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
return $project;
}
return View::create($form, 400);
}
因此,您基本上是在创建“无名”表单。 由于您正在构建API,因此最好将其放入基本控制器的createNamelessForm($type, $data, $options)
帮助器方法中,这样就不必从容器中显式地获取Form Factory了。时间,让眼睛更轻松。
包装器密钥不是由“ data_class”选项生成的,而是由表单类型上的“ getName()”方法生成的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.