簡體   English   中英

如何使用FOSRest和Symfony 3.0正確執行REST API POST調用

[英]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"}}

公平地說,這有點奇怪,僅發布屬性就足夠了。

因此,基於此信息,我僅有兩個問題:

  1. 為什么我需要使用($request->request->get($form->getName())) “提交”此表單,所以$request不夠嗎?
  2. 我需要為FormType更改什么以按原樣驗證實體,而不是在實體名稱前添加前綴?

編輯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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM