使用映射的 false 和多个 true 验证 symfony 4 formfield 文件类型
Validate symfony 4 formfield filetype with mapped false and multiple true
我有一个关于滑雪板技巧的项目。在我的项目中,我得到了一个实体 Trick,它的 itslef 有一个属性 "illustrations",它是另一个实体的集合:Illustration。我正在尝试做一个表单 TrickType,用户可以在其中一次加载许多插图(图像:png、jpeg、jpg、gif)。然后控制器保存文件,并创建几个插图实体,文件的名称和路径作为 "url" 属性。
因此,TrickType 无法直接管理插图实体,因为我必须在表单中使用 FileType 字段,这样才能加载文件,而 filetype 当然不会直接创建实体。这就是为什么我的 tricktype 表单中的文件类型字段必须具有以下选项:
- multiple : true(同时加载多个文件)
- mapped : false(Trick 中没有关于 url 的字段,只是插图实体的集合)
我的实体、表单和控制器已正确完成:如果我不对文件进行任何验证,或者如果我进行了验证,但只对一个文件进行验证,则一切正常。但我必须确保每个文件都是真正的图像。
这是我尝试这样做的:
1 - 直接在 TrickType 中进行约束:
->add('illustrations', FileType::class, [
"label" => "Illustrations (optionnel)",
"multiple" => true,
"mapped" => false,
"required" => false,
"constraints" => [
new File([
"maxSize" => "10M",
"mimeTypes" => [
"image/png",
"image/jpg",
"image/jpeg",
"image/gif"
],
"mimeTypesMessage" => "Veuillez envoyer une image au format png, jpg, jpeg ou gif, de 10 mégas octets maximum"
])
]
])
问题:约束尝试检查字段,它是一个集合而不是一个文件。所以我得到了错误 "this value should be of type string"
2 - 形式上没有约束,但在实体中
注意:此解决方案和以下解决方案不会阻止保存错误的文件,因为它只涉及实体,不涉及文件。所以即使它有效,它也只是防止从数据库中的 url 中找到错误的文件并放入网站,但它无论如何都不是一个很好的解决方案
插图实体中:
/**
* @ORM\Column(type="string", length=255)
* @Assert\Regex("/((.jpg)|(.jpeg)|(.png)|(.gif))$/")
*/
private $url;
在 Trick 实体中,尝试了 2 件事:
/**
* @ORM\OneToMany(targetEntity="App\Entity\Illustration", mappedBy="trick")
* @Assert\All({
* @Assert\Valid
* })
*/
private $illustrations;
error : "The constraint Valid cannot be nested inside constraint Symfony\Component\Validator\Constraints\All"
第二次尝试技巧:
/**
* @ORM\OneToMany(targetEntity="App\Entity\Illustration", mappedBy="trick")
* @Assert\Valid
*/
private $illustrations;
没有错误,但无论发生什么形式都被认为是有效的(我可以添加任何类型的文件,symfony 不会阻止我)
3 - none 我之前所做的,但在 Trick 实体中回调
/**
* @Assert\Callback
*/
public function checkIllustrations(ExecutionContextInterface $context, $payload)
{
$forbidenExtensions = false;
foreach ($this->illustrations as $illustration) {
$url = $illustration->getUrl();
if (! preg_match('/((.jpg)|(.jpeg)|(.png)|(.gif))$/', $url))
$forbidenExtensions = true;
}
if ($forbidenExtensions)
{
$context->buildViolation("L'un des fichiers semble ne pas être une image. Seuls les extensions jpg, jpeg, png et gif sont acceptés.")
->atPath("illustrations")
->addViolation();
}
}
这与之前的情况一样,当我只使用 Valid(不在 All 约束内)时没有做任何事情。就像什么都不勾选一样
添加
dump($this->illustrations);
die();
在我的回调开始时给我一个结果:一个空数组集合。当然,我会发送一些文件。
所以,回调被执行了,但是没有插图。
这让我想知道是否在我尝试提交表单时直接执行了回调(所以空插图是正常的:控制器创建之前没有插图)
有关信息,这是我在控制器中处理表单提交的方法:
/**
* @Route("/adding-trick", name="adding_trick")
* @IsGranted("ROLE_USER")
*/
public function addingTrick(Request $request, ObjectManager $manager)
{
$trick = new Trick();
$form = $this->createForm(TrickType::class, $trick);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$trick->setEditeur($this->getUser());
$illustrations = $form['illustrations']->getData();
if($illustrations)
{
foreach ($illustrations as $illustrationFile) {
$folder = "illustrations";
$extension = $illustrationFile->guessExtension();
if(!$extension)
$extension = "bin";
$illustrationName = rand(1, 999999999);
$illustrationFile->move($folder, $illustrationName . "." . $extension);
$illustration = new Illustration();
$illustration->setUrl("/" . $folder . "/" . $illustrationName . "." . $extension)
->setAlt("une illustration de la figure " . $trick->getNom())
->setTrick($trick);
$manager->persist($illustration);
$figure->addIllustration($illustration);
}
}
// some code for other fields
$manager->persist($figure);
$manager->flush();
$this->addFlash("success", "Figure ajoutée avec succès");
return $this->redirectToRoute("trick_display", [
"slug" => $trick->getSlug()
]);
}
return $this->render('handlingTricks/addingTrick.html.twig', [
"form" => $form->createView()
]);
}
如果有人知道我要做什么?
谢谢!
jakumi 在我的第一条消息下方的评论中给出了解决方案。这些是我的更改:
与第一次尝试一样,但有修改(新的全部包含新文件):
->add('illustrations', FileType::class, [
"label" => "Illustrations (optionnel)",
"multiple" => true,
"mapped" => false,
"required" => false,
"constraints" => [
new All([
new File([
"maxSize" => "10M",
"mimeTypes" => [
"image/png",
"image/jpg",
"image/jpeg",
"image/gif"
],
"mimeTypesMessage" => "Veuillez envoyer une image au format png, jpg, jpeg ou gif, de 10 mégas octets maximum"
])
])
]
])
我有一个关于滑雪板技巧的项目。在我的项目中,我得到了一个实体 Trick,它的 itslef 有一个属性 "illustrations",它是另一个实体的集合:Illustration。我正在尝试做一个表单 TrickType,用户可以在其中一次加载许多插图(图像:png、jpeg、jpg、gif)。然后控制器保存文件,并创建几个插图实体,文件的名称和路径作为 "url" 属性。
因此,TrickType 无法直接管理插图实体,因为我必须在表单中使用 FileType 字段,这样才能加载文件,而 filetype 当然不会直接创建实体。这就是为什么我的 tricktype 表单中的文件类型字段必须具有以下选项:
- multiple : true(同时加载多个文件)
- mapped : false(Trick 中没有关于 url 的字段,只是插图实体的集合)
我的实体、表单和控制器已正确完成:如果我不对文件进行任何验证,或者如果我进行了验证,但只对一个文件进行验证,则一切正常。但我必须确保每个文件都是真正的图像。
这是我尝试这样做的:
1 - 直接在 TrickType 中进行约束:
->add('illustrations', FileType::class, [
"label" => "Illustrations (optionnel)",
"multiple" => true,
"mapped" => false,
"required" => false,
"constraints" => [
new File([
"maxSize" => "10M",
"mimeTypes" => [
"image/png",
"image/jpg",
"image/jpeg",
"image/gif"
],
"mimeTypesMessage" => "Veuillez envoyer une image au format png, jpg, jpeg ou gif, de 10 mégas octets maximum"
])
]
])
问题:约束尝试检查字段,它是一个集合而不是一个文件。所以我得到了错误 "this value should be of type string"
2 - 形式上没有约束,但在实体中
注意:此解决方案和以下解决方案不会阻止保存错误的文件,因为它只涉及实体,不涉及文件。所以即使它有效,它也只是防止从数据库中的 url 中找到错误的文件并放入网站,但它无论如何都不是一个很好的解决方案
插图实体中:
/**
* @ORM\Column(type="string", length=255)
* @Assert\Regex("/((.jpg)|(.jpeg)|(.png)|(.gif))$/")
*/
private $url;
在 Trick 实体中,尝试了 2 件事:
/**
* @ORM\OneToMany(targetEntity="App\Entity\Illustration", mappedBy="trick")
* @Assert\All({
* @Assert\Valid
* })
*/
private $illustrations;
error : "The constraint Valid cannot be nested inside constraint Symfony\Component\Validator\Constraints\All"
第二次尝试技巧:
/**
* @ORM\OneToMany(targetEntity="App\Entity\Illustration", mappedBy="trick")
* @Assert\Valid
*/
private $illustrations;
没有错误,但无论发生什么形式都被认为是有效的(我可以添加任何类型的文件,symfony 不会阻止我)
3 - none 我之前所做的,但在 Trick 实体中回调
/**
* @Assert\Callback
*/
public function checkIllustrations(ExecutionContextInterface $context, $payload)
{
$forbidenExtensions = false;
foreach ($this->illustrations as $illustration) {
$url = $illustration->getUrl();
if (! preg_match('/((.jpg)|(.jpeg)|(.png)|(.gif))$/', $url))
$forbidenExtensions = true;
}
if ($forbidenExtensions)
{
$context->buildViolation("L'un des fichiers semble ne pas être une image. Seuls les extensions jpg, jpeg, png et gif sont acceptés.")
->atPath("illustrations")
->addViolation();
}
}
这与之前的情况一样,当我只使用 Valid(不在 All 约束内)时没有做任何事情。就像什么都不勾选一样
添加
dump($this->illustrations);
die();
在我的回调开始时给我一个结果:一个空数组集合。当然,我会发送一些文件。
所以,回调被执行了,但是没有插图。
这让我想知道是否在我尝试提交表单时直接执行了回调(所以空插图是正常的:控制器创建之前没有插图)
有关信息,这是我在控制器中处理表单提交的方法:
/**
* @Route("/adding-trick", name="adding_trick")
* @IsGranted("ROLE_USER")
*/
public function addingTrick(Request $request, ObjectManager $manager)
{
$trick = new Trick();
$form = $this->createForm(TrickType::class, $trick);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$trick->setEditeur($this->getUser());
$illustrations = $form['illustrations']->getData();
if($illustrations)
{
foreach ($illustrations as $illustrationFile) {
$folder = "illustrations";
$extension = $illustrationFile->guessExtension();
if(!$extension)
$extension = "bin";
$illustrationName = rand(1, 999999999);
$illustrationFile->move($folder, $illustrationName . "." . $extension);
$illustration = new Illustration();
$illustration->setUrl("/" . $folder . "/" . $illustrationName . "." . $extension)
->setAlt("une illustration de la figure " . $trick->getNom())
->setTrick($trick);
$manager->persist($illustration);
$figure->addIllustration($illustration);
}
}
// some code for other fields
$manager->persist($figure);
$manager->flush();
$this->addFlash("success", "Figure ajoutée avec succès");
return $this->redirectToRoute("trick_display", [
"slug" => $trick->getSlug()
]);
}
return $this->render('handlingTricks/addingTrick.html.twig', [
"form" => $form->createView()
]);
}
如果有人知道我要做什么?
谢谢!
jakumi 在我的第一条消息下方的评论中给出了解决方案。这些是我的更改:
与第一次尝试一样,但有修改(新的全部包含新文件):
->add('illustrations', FileType::class, [
"label" => "Illustrations (optionnel)",
"multiple" => true,
"mapped" => false,
"required" => false,
"constraints" => [
new All([
new File([
"maxSize" => "10M",
"mimeTypes" => [
"image/png",
"image/jpg",
"image/jpeg",
"image/gif"
],
"mimeTypesMessage" => "Veuillez envoyer une image au format png, jpg, jpeg ou gif, de 10 mégas octets maximum"
])
])
]
])