模型转换器不调用 Symfony3 表单验证以供现场使用
Symfony3 form validation not called for field use by a model transformer
编辑:这里是 github 以及重现问题的完整代码
我有以下实体
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;
}
具有以下形式
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']);
}
}
以及以下型号变压器
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);
}
}
我可以上传正确的图片,并且表格已正确保存在数据库中。
但是,如果我提交了不正确的图片(例如 .txt 文件),表单仍会毫无错误地保存在数据库中
但是,如果我从表单中删除 addModelTransformer
,则会得到正确的验证错误
This file is not a valid image
因为我的转换器没有修改原来的 imageFile
字段,我想知道是什么导致了这个问题。
我正在使用 php7 和 symfony3.3.4
您的转换器正在用 MyImage
实体替换 UploadFile
或 File
对象。我假设您的 MyImage
没有扩展 File
或 UploadFile
。这不是变压器的预期用途。变压器将一种输入转换为另一种输入。
我建议删除转换器并将转换器的代码添加到Place->setImageFile
中。然后您将按预期进行 imageFile 验证,并且每次您将图像更改为另一个文件时,您将重新创建 MyImage
,即使您没有使用表单。
如果您真的想在表单代码中而不是在 Place 实体代码中这样做,您应该使用 FormEvents https://symfony.com/doc/current/form/events.html FormEvents: :POST_SET_DATA
要导致验证错误,请抛出 TransformationFailedException。但是您传递给此异常的消息不会显示给用户。您将使用 invalid_message 选项设置该消息(见下文)。
https://symfony.com/doc/current/form/data_transformers.html
答案其实很蠢
原因是我在reverseTransform
中忘记了一个return
/**
* 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;
}
这导致整个实体 以模型 的形式被转换为 "null" 但实体本身并没有被破坏,因为我仍然在通过标准
创建的控制器
public function createAction(Request $request)
{
$place = new Place();
$form = $this->createForm(AdminPlaceType::class, $place);
$form->handleRequest($request);
}
所以 $place
包含正确的数据,并且具有 null
的表单没有触发验证....
编辑:这里是 github 以及重现问题的完整代码
我有以下实体
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;
}
具有以下形式
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']);
}
}
以及以下型号变压器
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);
}
}
我可以上传正确的图片,并且表格已正确保存在数据库中。
但是,如果我提交了不正确的图片(例如 .txt 文件),表单仍会毫无错误地保存在数据库中
但是,如果我从表单中删除 addModelTransformer
,则会得到正确的验证错误
This file is not a valid image
因为我的转换器没有修改原来的 imageFile
字段,我想知道是什么导致了这个问题。
我正在使用 php7 和 symfony3.3.4
您的转换器正在用 MyImage
实体替换 UploadFile
或 File
对象。我假设您的 MyImage
没有扩展 File
或 UploadFile
。这不是变压器的预期用途。变压器将一种输入转换为另一种输入。
我建议删除转换器并将转换器的代码添加到Place->setImageFile
中。然后您将按预期进行 imageFile 验证,并且每次您将图像更改为另一个文件时,您将重新创建 MyImage
,即使您没有使用表单。
如果您真的想在表单代码中而不是在 Place 实体代码中这样做,您应该使用 FormEvents https://symfony.com/doc/current/form/events.html FormEvents: :POST_SET_DATA
要导致验证错误,请抛出 TransformationFailedException。但是您传递给此异常的消息不会显示给用户。您将使用 invalid_message 选项设置该消息(见下文)。 https://symfony.com/doc/current/form/data_transformers.html
答案其实很蠢
原因是我在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;
}
这导致整个实体 以模型 的形式被转换为 "null" 但实体本身并没有被破坏,因为我仍然在通过标准
创建的控制器 public function createAction(Request $request)
{
$place = new Place();
$form = $this->createForm(AdminPlaceType::class, $place);
$form->handleRequest($request);
}
所以 $place
包含正确的数据,并且具有 null
的表单没有触发验证....