2

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

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

  • 多个: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()
        ]);
    }

如果有人知道我要做什么?

谢谢 !

4

1 回答 1

4

在我的第一条消息下方的评论中给出了解决方案 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"
                        ])
                    ])
                ]
            ])
于 2019-12-20T18:52:46.317 回答