Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symfony2 FOSRestBundle PUT Action FORM returns empty results

I am using Symfony 2.2 and the latest version of FOSRestBundle. So I have manage to make most of the actions work but I seem to have an issue with the FormBuilder that I am passing the Request of my PUT call in.

I have checked the request object and it comes from my Backbone.je model as it should (.save()) But after binding to the form the entity comes back with only the id which causes flush() to throw an error since required fields are not filled.

The action in the Controller:

header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS ');
header('Allow GET, POST, PUT, DELETE, OPTIONS ');
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: Content-Type, *');

use FOS\RestBundle\Controller\FOSRestController;
use FOS\RestBundle\Controller\Annotations as Rest;
use FOS\RestBundle\Routing\ClassResourceInterface;
use FOS\Rest\Util\Codes;
use Symfony\Component\HttpFoundation\Request;
use Greenthumbed\ApiBundle\Entity\Container;
use Greenthumbed\ApiBundle\Form\ContainerType;

class ContainerController extends FOSRestController implements ClassResourceInterface
{
/**
 * Put action
 * @var Request $request
 * @var integer $id Id of the entity
 * @return View|array
 */
public function putAction(Request $request, $id)
{
    $entity = $this->getEntity($id);
    $form = $this->createForm(new ContainerType(), $entity);
    $form->bind($request);

    if ($form->isValid()) {
        $em = $this->getDoctrine()->getManager();
        $em->persist($entity);
        $em->flush();

        return $this->view(null, Codes::HTTP_NO_CONTENT);
    }

    return array(
        'form' => $form,
    );
}

/**
 * Get entity instance
 * @var integer $id Id of the entity
 * @return Container
 */
protected function getEntity($id)
{
    $em = $this->getDoctrine()->getManager();

    $entity = $em->getRepository('GreenthumbedApiBundle:Container')->find($id);

    if (!$entity) {
        throw $this->createNotFoundException('Unable to find Container entity');
    }

    return $entity;
}

The Form that is called:

namespace Greenthumbed\ApiBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class ContainerType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name')
            ->add('description')
            ->add('isVisible')
            ->add('type')
            ->add('size')
            ->add('creationDate')
            ->add('userId')
        ;
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Greenthumbed\ApiBundle\Entity\Container',
            'csrf_protection' => false,
        ));
    }

    public function getName()
    {
        return 'greenthumbed_apibundle_containertype';
    }
}

I have tried everything so far but I am fairly new with Symfony and I cannot understand why the $entity does not contain the values received by the request.

FYI: I have tried doing it manually as in instantiating a Container class with the ID of the request and putting use the setters to input values into it and it works just fine, I just want to do things the right way as Symfony suggests it should be done.

Thank you very much in advance.

like image 464
Dimitris Romeo Havlidis Avatar asked Jun 07 '13 04:06

Dimitris Romeo Havlidis


2 Answers

Try changing the following line in putAction:

$form = $this->createForm(new ContainerType(), $entity);

to:

$form = $this->createForm(new ContainerType(), $entity, array('method' => 'PUT'));
like image 85
ebonhand Avatar answered Oct 24 '22 13:10

ebonhand


I think you are experiencing the same problem I had: The mistake is in the name of the Form.

In your Form definition the name is "greenthumbed_apibundle_containertype". public function getName() { return 'greenthumbed_apibundle_containertype'; }

So to bind a request to this form the json should have looked like this:

{"greenthumbed_apibundle_containertype": [{"key": "value"}]}

Since Backbone .save() method ship this kind of json

{"key":"value","key2":"value2"}

you have to remove the name from the Form:

public function getName()
{
    return '';
}

In general if you want to post a json with a placeholder like

"something":{"key":"value"}

your form name must be exactly "something"

from my own question here

like image 38
rollsappletree Avatar answered Oct 24 '22 15:10

rollsappletree