Search code examples
phpformssymfonyfosrestbundle

Invalid Form in Symfony with no errors


This is the first time I've tried to use forms with Symfony, and I've got myself completely stuck. I'm sure it will be something simple.

I have a simple controller set up as so (using Symfony 2.7 and FOSRestBundle 2.0):

/**
 * @View()
 */
public function postPredictionsAction(Request $request)
{
    $form = $this->createFormBuilder(['id' => '1', 'description' => '2'])
        ->add('id', 'text')
        ->add('description', 'text')
        ->getForm();
    $form->handleRequest($request);

    if ($form->isValid()) {
        return true;
    }

    print_r($request->request->all());
    print_r($form->getData());
    print_r((string) $form->getErrors(true, false));

    return false;
}

But my form is always invalid, even though there are no errors:

curl -X POST --data 'id=foo&description=bar' http://localhost:8080/bracket/predictions
Array
(
    [id] => foo
    [description] => bar
)
Array
(
    [id] => 1
    [description] => 2
)
false

So it looks like my request data is not making it in to the form, and for some reason the form is not valid, even though there are no errors printed at all.

EDIT: After a lot of faffing around, it seems that the handleRequest() call has determined that the form has not been submitted, and therefore is not validated - meaning I get in to the situation described above.

So instead of handleRequest() I can replace it with submit() as a work around. This is described as deprecated behaviour by the docs:

http://symfony.com/doc/2.7/cookbook/form/direct_submit.html#cookbook-form-submit-request

So I'm clearly still doing something wrong, but I can't see what it is from the Symfony docs.


Solution

  • I've determined what the problem was.

    When posting data like I was, by default Symfony expects it to be encapsulated in the name of the form. For example, with JSON:

    {
      "form": {
        "id": "12",
        "name": "abc"
      }
    }
    

    Now for RESTful APIs that isn't what I wanted (nor I suspect the behaviour most people want or expect), so instead you can do the following in the code:

    /**
     * @View()
     */
    public function postPredictionsAction(Request $request)
    {
        $form = $this->createFormBuilder(['id' => '1', 'description' => '2'])
            ->add('id', 'text')
            ->add('description', 'text')
            ->getForm();
    
        // NOTE: we use submit here, but pass the data as an array, thus
        // making it Symfony 3 compatible
        $form->submit($request->request->all());
    
        if ($form->isValid()) {
            // Do valid work
        }
    
        // Output validation errors
        return $form;
    }
    

    And that works just fine with the following JSON:

    {
      "id": "12",
      "name": "abc"
    }
    

    Hope that helps someone else avoiding the rabbit hole I went down discovering this the hard way!