Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symfony3 form validation not called for field use by a model transformer

Edit: here's a github with the full code to reproduce the problem

I have the following entity

class Place
{
    use Traits\HasId;

    /**
     * Used for form.
     *
     * @Assert\Image(
     *     mimeTypes = {"image/png", "image/jpeg"},
     *     minWidth = 50,
     *     maxWidth = 1000,
     *     minHeight = 50,
     *     maxHeight = 1000,
     *     maxSize = "1M"
     * )
     */
    private $imageFile = null;

    /**
     * @ORM\OneToOne(targetEntity="MyImage", orphanRemoval=true, cascade={"persist"})
     */
    protected $image;

}

With the following form

class AdminPlaceType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $transformer = new HasImageTransformer();
        $builder->add('imageFile')->addModelTransformer($transformer);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(['data_class' => 'AppBundle\Entity\Place']);
    }
}

And the following model transformer

class HasImageTransformer implements DataTransformerInterface
{   
    public function transform($hasImage)
    {
        return $hasImage;
    }

    /**
     * reverse transforms.
     */
    public function reverseTransform($hasImage)
    {   
        $file = $hasImage->getImageFile();
        $myImage = new MyImage();
        $myImage->setData(file_get_contents($file->getPathName()))
        $myImage->setMimeType($file->getMimeType());

        $hasImage->setImage($myImage);
    }
}

I can upload a correct image, and the form is correctly saved in database.

However if I submit an incorrect image (for example a .txt file), the form is still saved in database without any error

However if I remove the addModelTransformer from the Form, then I got the correct validation error

This file is not a valid image

as my transformer does not modify the original imageFile field, I'm wondering what could cause this problem.

I'm using php7 and symfony3.3.4

like image 495
allan.simon Avatar asked Jul 17 '17 22:07

allan.simon


People also ask

How do I use issuetonumbertransformer in Symfony?

If you're using the default services.yaml configuration , Symfony will automatically know to pass your TaskType an instance of the IssueToNumberTransformer thanks to autowire and autoconfigure . Otherwise, register the form class as a service and tag it with the form.type tag.

How do I validate all the classes stored in Symfony?

You can also validate all the classes stored in a given directory: The Symfony validator is a powerful tool that can be leveraged to guarantee that the data of any object is "valid". The power behind validation lies in "constraints", which are rules that you can apply to properties or getter methods of your object.

How do I validate an author object in Symfony?

Symfony's validator uses PHP reflection, as well as "getter" methods, to get the value of any property, so they can be public, private or protected (see Validation ). Next, to actually validate an Author object, use the validate () method on the validator service (which implements ValidatorInterface ).

What is a data transformer in Salesforce form?

Internally, a data transformer converts the starting DateTime value of the field into the yyyy-MM-dd string to render the form, and then back into a DateTime object on submit. When a form field has the inherit_data option set to true, data transformers are not applied to that field.


2 Answers

The answer was actually pretty stupid

The reason was that I forgot a return in the reverseTransform

/**
 * reverse transforms.
 */
public function reverseTransform($hasImage)
{   
    $file = $hasImage->getImageFile();
    $myImage = new MyImage();
    $myImage->setData(file_get_contents($file->getPathName()))
    $myImage->setMimeType($file->getMimeType());

    $hasImage->setImage($myImage);
    // this was missing :(
    return $hasImage;
}

This was causing the whole entity in the form model to be transformed as "null" BUT the entity itself was not destroyed because I had still reference to it in the controller as it was created through the standard

  public function createAction(Request $request)
  {   
      $place = new Place();

      $form = $this->createForm(AdminPlaceType::class, $place);
      $form->handleRequest($request);
  }

so the $place was containing the correct data, and the form having null it was not triggering validation....

like image 167
allan.simon Avatar answered Oct 17 '22 07:10

allan.simon


Your transformer is replacing a UploadFile or File object by MyImage entity. I assume your MyImage is not extending File or UploadFile. This is not the intended use for a transformer. A transformer change one input to another type of input.

I would recommend to remove the transformer and add the code of the transformer into Place->setImageFile. Then you will have the imageFile validation as expected and every time you change the image by another file you will recreate your MyImage even when you are not using the form.

If you really want to do that in the form code and not in the Place entity code you should use the FormEvents https://symfony.com/doc/current/form/events.html FormEvents::POST_SET_DATA

like image 2
albert Avatar answered Oct 17 '22 06:10

albert