验证具有映射的false和多个true的symfony 4表单域文件类型

问题描述 投票:0回答:1

我有一个有关滑雪技巧的项目。在我的项目中,我得到了一个实体Trick,其itlef具有属性“ illustrations”,该属性是另一个实体的集合:Illustration。我正在尝试做一个TrickType形式,用户可以在其中一次加载许多插图(图像:png,jpeg,jpg,gif)。然后,控制器保存文件,并创建几个插图实体,文件的名称和路径作为“ url”属性。

因此,TrickType无法直接管理插图实体,因为我必须以这种方式在表单中使用FileType字段,从而可以加载文件,并且文件类型当然不会直接创建实体。这就是为什么我的技巧类型表单中的文件类型字段必须具有以下选项的原因:

  • 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"
                    ])
                ]
            ])

问题:约束尝试检查该字段,它是一个集合而不是文件。所以我收到错误消息“此值应为字符串类型”

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;

错误:“约束Valid不能嵌套在约束Symfony \ Component \ Validator \ Constraints \ All中”

第二招:

/**
     * @ORM\OneToMany(targetEntity="App\Entity\Illustration", mappedBy="trick")
     * @Assert\Valid
     */
    private $illustrations;

没有错误,但是无论发生什么形式都被认为是有效的(我可以添加任何类型的文件,symfony不会阻止我)

3-我之前没有做过,但在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();

在我的回调的开头给我一个结果:一个空的arraycollection。当然,我发送一些文件。

因此,执行了回调,但没有说明。

这使我想知道在尝试提交表单时是否直接执行了回调(因此,空插图是正常的:控制器创建它之前没有任何插图)

有关信息,这是我在控制器中处理表单提交的方法:

    /**
     * @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()
        ]);
    }

如果有人对我要做的事情有所了解?

谢谢!

symfony constraints symfony4 symfony-4.3
1个回答
0
投票

我的第一条消息下方的评论中给了jakumi解决方案。这些是我的改动:

第一次尝试,但有修改(new全部包含新文件):

->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"
                        ])
                    ])
                ]
            ])
© www.soinside.com 2019 - 2024. All rights reserved.