How to correctly execute a REST POST request call using FOSRest and Symfony 3.0

For the API that I am creating now, I would like to send a request with a JSON body with the following contents

{"title": "foo"} 

to create a new database entry for an object called Project .

I created a controller that subclasses FOSRestController . To create a project, I took an action

 /** * @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 as follows

 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' )); } } 

However, when I try to publish JSON in the API, it responds that the title property cannot be empty, which is good because it has a validation rule set. However, it is installed. I suddenly realized that I had to send JSON with a prefix of the actual name of the object to make this work:

 {"project":{"title": "bla"}} 

Which seems a little strange to be fair, that should be enough to just post the properties.

So, based on this information, I just have 2 questions:

  • Why do I need to "submit" this form using ($request->request->get($form->getName())) rather than $request being enough?
  • What do I need to change for FormType to check the object as is, instead of prefixing it with the name of the entity?

Edit 1: adding or removing data_class in the default settings does not change the behavior at all.

+5
source share
1 answer

This is due to how the helper method of Symfony Controller "createForm" works. The reason is that multiple forms may have the same destination URL. A prefix with the name of the form, Symfony can know which form was submitted.

This can be seen by looking at the implementation of the createForm method:

 public function createForm($type, $data = null, array $options = array()) { return $this->container->get('form.factory')->create($type, $data, $options); } 

If you do not want this behavior, it is very easy to change it:

 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); } 

So, you basically create a "nameless" form. Since you are creating an API, it is probably a good idea to pull this into the createNamelessForm($type, $data, $options) helper method in your base controller so that you donโ€™t have to constantly get the Factory form from the container and simplify it before our eyes.

Comment on editing

The wrapper key is not generated by the "data_class" option, but by the getName () method in your form type.

+5
source

Source: https://habr.com/ru/post/1240035/


All Articles