简体   繁体   中英

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

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....

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

To cause a validation error, throw a TransformationFailedException. But the message you pass to this exception won't be shown to the user. You'll set that message with the invalid_message option (see below). https://symfony.com/doc/current/form/data_transformers.html

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM