Search code examples
phprestsymfonyfosrestbundle

Symfony and FOSRestBundle: form not filling entity data


I'm trying to build a very simple rest api with FOS Rest bundle. The GET and DELETE methods were easy, but I'm struggling with post.

Here's my post method of a very simple entity (only has a "name" and "active" property):

/**
     * @param Request $request
     * @return array|View
     */
    public function postSkillsAction(Request $request)
    {
        $skill = new Skill();

        $form = $this->createForm(SkillType::class, $skill);

        $form->submit($request->request->get($form->getName()));

        if ($form->isSubmitted() && $form->isValid()) {
            $this->entityManager->persist($skill);
            $this->entityManager->flush();
            return $this->redirectToRoute('skillset', ['id' => $skill->getId()], Response::HTTP_CREATED);
        }

        return [
            'form' => $form
        ];
    }

And this is my form:

final class SkillType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options) : void
    {
        $builder
            ->add(
                'name', TextType::class, [
                'label' => 'fields.name'
            ])
            ->add('active', CheckboxType::class, [
                'label' => 'fields.active',
                'required' => false
            ]);
    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class'      => Skill::class,
            'csrf_protection' => false
        ]);
    }

    /**
     * @return string
     */
    public function getName() : string
    {
        return 'skill';
    }

}

The problem is that it seems like the form is not filling the entity data, when I execute /api/skills sending by post name and active I get the following SQL error

An exception occurred while executing 'INSERT INTO skill (name, active, created_at, updated_at) VALUES (?, ?, ?, ?)' with params [null, 0, "2017-03-19 19:49:37", "2017-03-19 19:49:37"]

The form data arrives correctly, I've debug and if I do $request->request->get('name') I got the proper value.

I couldn't find any updated example, this one for instance is for symfony 2, although I tried to follow it as much as possible https://github.com/gimler/symfony-rest-edition/blob/2.7/src/AppBundle/Controller/NoteController.php

UPDATE If I do a var_dump of var_dump($request->request->all()); I get

array(
'name' => a,
'active' => 1
)

And here's the entity

final class Skill
{
    use OptionalDateTimeTrait;

    /**
     * @var integer
     */
    private $id;

    /**
     * @var string
     */
    private $name;

    /**
     * @var integer
     */
    private $active;

    /**
     * @return int
     */
    public function getId(): int
    {
        return $this->id;
    }

    /**
     * @param int $id
     * @return Skill
     */
    public function setId(int $id) : self
    {
        $this->id = $id;

        return $this;
    }

    /**
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * @param string $name
     * @return self
     */
    public function setName(string $name) : self
    {
        $this->name = $name;
        return $this;
    }

    /**
     * Set active
     *
     * @param boolean $active
     *
     * @return Skill
     */
    public function setActive($active) : self
    {
        $this->active = $active;

        return $this;
    }

    /**
     * Get active
     *
     * @return boolean
     */
    public function getActive()
    {
        return $this->active;
    }
}

Solution

  • As you've told us, when you're calling $request->request->get('name') you get correct value. Please take a look at your code where you pass data to form:

    $form->submit($request->request->get($form->getName()));
    

    This line of code means that you're passing to form only those data, which comes as array named as your form (in your case - skill). In this case you should pass through POST such data:

    skill[name]=John
    skill[active]=1
    

    If you want not to send data through POST using array wrapper, you have to submit to your form whole request:

    $form->submit($request->request->all());
    

    Both methods are technically correct, but second is in fact anti-pattern.