Por qué Symfony File Validator no funciona

I want to use file validator to restrict mime types for file input. Unfortunately this constraint is never used and all files were accepted.

namespace WNC\SoldierBundle\Entity;

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

/**
* WNC\SoldierBundle\Entity\Soldier
*
* @ORM\Table(name="soldier")
* @ORM\Entity(repositoryClass="WNC\SoldierBundle\Entity\SoldierRepository")
* @ORM\HasLifecycleCallbacks()
*/
class Soldier
{

   /**
    * @var string $picture
    * @Assert\Image()
    * @ORM\Column(name="picture", type="string", length=255)
    */
    private $picture;

    /**
    * @var string $file
    * 
    * @Assert\Image()
    * @Assert\NotBlank()
    */
    public $file;


    public function getAbsolutePath()
    {
        return null === $this->picture ? null : $this->getUploadRootDir().'/'.$this->picture;
    }

    public function getWebPath()
    {
        return null === $this->picture ? null : $this->getUploadDir().'/'.$this->picture;
    }

    protected function getUploadRootDir()
    {
        // the absolute directory path where uploaded documents should be saved
        return __DIR__.'/../../../../web/'.$this->getUploadDir();
    }

    protected function getUploadDir()
    {
        // get rid of the __DIR__ so it doesn't screw when displaying uploaded doc/image in the view.
        return 'uploads/pictures';
    }

    /**
    * @ORM\PrePersist()
    * @ORM\PreUpdate()
    */
    public function preUpload()
    {

        if($this->picture && file_exists($this->getAbsolutePath())) {
            unlink($this->getAbsolutePath());
        }

        if (null !== $this->file) {
            // do whatever you want to generate a unique name
            $this->picture = uniqid().'.'.$this->file->guessExtension();
        }

    }

    /**
    * @ORM\PostPersist()
    * @ORM\PostUpdate()
    */
    public function upload()
    {
        if (null === $this->file) {
            return;
        }


        // if there is an error when moving the file, an exception will
        // be automatically thrown by move(). This will properly prevent
        // the entity from being persisted to the database on error
        $this->file->move($this->getUploadRootDir(), $this->picture);

    }

    /**
    * @ORM\PostRemove()
    */
    public function removeUpload()
    {
        if ($file = $this->getAbsolutePath()) {
            unlink($file);
        }
    }
}

Creador de formularios:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('mothers_name')
        ->add('service_end_date', 'date',array(
            'widget' => 'single_text',
            'format' => 'MM/dd/yyyy',
            'attr' => array('class' => 'date six columns')
        ))
        ->add('army_unit')
        ->add('city', 'city_selector')
        ->add('gender', 'choice', array(
            'choices'   => array(0 => 'Male', 1 => 'Female'),
            'required'  => false,
            'expanded' => true,
            'label' => 'Male / Female',
            'data' => 0
        ))
        ->add('file','file', array(
          'data_class' => 'Symfony\Component\HttpFoundation\File\File',
          'label' => 'Picture'
        ))
        ->add('self_description', 'textarea')
        ->add('video', null, array(
            'attr' => array(
            'placeholder' => 'some link here'
        )))
        ->add('wants_to_contact', null, array(
            'label' => Soldier::getLabel('wants_to_contact')
        ))
        ->add('comments', 'textarea')
        ->add('user', new NameFormType('Application\Sonata\UserBundle\Entity\User')) 
        ->add('city', 'city_selector')

    ;


}

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setDefaults(array(
        'validation_groups' => array('Registration'),
        'cascade_validation' => true,
    ));


}

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

Controlador:

/**
 * Creates a new Soldier entity.
 *
 * @Route("/create", name="soldier_create")
 * @Method("POST")
 * @Template("WNCSoldierBundle:Soldier:new.html.twig")
 */
public function createAction(Request $request)
{
    $entity  = new Soldier();
    $form = $this->createForm(new SoldierType(), $entity);
    $form->bind($request);

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

        $em->persist($entity);
        $em->flush();

        return $this->redirect($this->generateUrl('soldier_show', array('id' => $entity->getId())));
    }

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

preguntado el 28 de agosto de 12 a las 14:08

Different topic: I have noticed you are having the same problem I have with paths, you might wanna check this out: stackoverflow.com/questions/12168086/… -

thanks, but saving works flawless but I can't find a reason why validation is not working. Maybe because it is only a virtual field not used as db column? -

I just created a test app that uses this assert and it worked fine. Non images gave an error, and images went through. This is on Symfony2.1. What does your form builder look like? -

@Kris could You send me link to your app maybe this will help. I have updated post so it includes form builder code. -

3 Respuestas

Check out this previous SO question: La validación de Symfony2 usando la anotación Assert no funciona. You might want to ensure you have met all the recommended configurations to use Symfony2.

Also, it isn't necessary to validate $picture con Image constraint because it isn't a file/image.

/**
 * @var string $picture
 * @Assert\Image()                                        <-- Should be removed
 * @ORM\Column(name="picture", type="string", length=255)
 */
 private $picture; 

/**
 * @var string $file                                      <-- @var UploadedFile $file
 * 
 * @Assert\Image()
 * @Assert\NotBlank()
 */
 public $file;

I was actually able to validate that an uploaded file is an image using the YAML alternative so you might also want to try that if nothing comes up.

contestado el 23 de mayo de 17 a las 13:05

Thanks for answer, unfortunatelly Your suggestions didn't fix the problem. The link that you provided is related with other validator than i'm using. I have no problem with standard validators like required, non empty etc. I checked VichUploaderBundle and removed lifecycle annotations but it doesn't make the difference. What symfony version are you using? - lucas adamczewski

on the other hand yml validation file was also ineffective in this case - lucas adamczewski

Hi @LukeAdamczewski, yes I am aware the link I provided was about a different validator. What I think was useful there though was actually this answer stackoverflow.com/a/7946408/1349295 regarding the intl extension. Perhaps ensure all recommended configurations for sf2 are met? BTW, I got this working on sf2.0. I've been porting some code from 2.1 to 2.0 and encountered some significant changes (and still changing). Incidentally, sf2.1 is no longer on beta! Just checked right now. Maybe try upgrading to the latest distribution. :) - Zar Pino

I found the solution. In form definition i am using `'validation_groups' => array('Registration'). I thought that when there is no group for validator it will match to any of them in form definition.

When i have added groups property to validator everything was working finally. So for example using validation.yml:

WNC\SoldierBundle\Entity\Soldier:
    properties:
        file:
            - Image: {groups: [Registration]}

Respondido el 10 de Septiembre de 12 a las 12:09

You using Constraint which isn't suitable for your field. Just stick with File constraint on $file property.

contestado el 24 de mayo de 15 a las 16:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.