Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

symfony2's FOSRestController can't validate an ajax post request

I'm developing a Symfony 2.6.1 application and I have a form I render with the FormTypes and an Entity using annotations as validation. The form is submitted an AJAX POST call to a FOSRestController. The thing is the isValid() function is returning FALSE and I get no error messages...

My FOSRestController looks as follows:

class RestGalleryController extends FOSRestController{

    /**
     * @Route(requirements={"_format"="json"})
     */
    public function postGalleriesAction(\Symfony\Component\HttpFoundation\Request $request){

        return $this->processForm(new \Law\AdminBundle\Entity\Gallery());   
    }
    private function processForm(\Law\AdminBundle\Entity\Gallery $gallery){

        $response = array('result' => 'Default');

        $gallery->setName('TEST'); //Just added this to be sure it was a problem with the validator
        $form = $this->createForm(
            new \Law\AdminBundle\Form\Type\GalleryType(), 
            $gallery
        );
        $form->handleRequest($this->getRequest());

        if ($form->isValid()) {

            $response['result'] = 'Is Valid!';
        }else{
            var_dump( $form->getErrorsAsString() );
            die;           
        }
        return $response;
    }

My Gallery Entity class below:

<?php

namespace Law\AdminBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\ORM\Mapping as ORM;

/**
 * Gallery
 *
 * @ORM\Table(name="gallery")
 * @ORM\Entity
 */
class Gallery{

    /**
     * @var string
     * @Assert\NotBlank()
     * @ORM\Column(name="name", type="text", nullable=false)
     */
    private $name;

    public function __construct(){
        $this->images = new ArrayCollection();
    }
    /**
     * Set name
     *
     * @param string $name
     * @return Gallery
     */
    public function setName($name){
        $this->name = $name;

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

The GalleryType, encapsulating the form:

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

class GalleryType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options){
        $builder->add('name');
    }
    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class'        => 'Law\AdminBundle\Entity\Gallery',
            'csrf_protection'   => false,
        ));
    }
    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'Gallery';
    }
}

Finally, In my app/config/config.yml, the validation is set up as follows:

validation:      { enable_annotations: true }

To get the validation error I've also tried with the following function, unsuccessfully :

private function getErrorMessages(\Symfony\Component\Form\Form $form) {
    $errors = array();

    foreach ($form->getErrors() as $key => $error) {
        if ($form->isRoot()) {
            $errors['#'][] = $error->getMessage();
        } else {
            $errors[] = $error->getMessage();
        }
    }

    foreach ($form->all() as $child) {
        if (!$child->isValid()) {
            $errors[$child->getName()] = $this->getErrorMessages($child);
        }
    }

    return $errors;
} 

EDIT:

If I manually use a validator, it works:

    $formGallery = new Gallery();
    $formGallery->setName($this->getRequest()->get('name', NULL));
    $validator = $this->get('validator');
    $errors = $validator->validate($formGallery);

So it's like somehow my GalleryType wasn't using the validator.

like image 463
MiGU Avatar asked Apr 30 '16 22:04

MiGU


1 Answers

This is because you are using handleRequest with empty submitted data I guess. In such scenario you such call:

// remove form->handleRequest call
// $form->handleRequest($this->getRequest());
$form->submit($request->request->all());

as handleRequest will auto-submit form unless one field is present. When you handle request with empty array form is not being submitted, thats why isValid return false with no errors.

Note: check if you are sending empty POST array or something like:

`Gallery` => []

If you are sending empty Gallery array everything should work as expected.

Could you paste data that you are sending via AJAX request?

like image 98
Kamil Adryjanek Avatar answered Oct 13 '22 18:10

Kamil Adryjanek