如何在 Symfony 5 中使用 vich 上传器上传多个文件

How to upload multiple files with vich uploader in Symfony 5

在尝试使用 collectionTypeformtype 中的 vichuploader 上传多个文件时给出的预期参数类型为“AppBundle\Entity\File”、“AppBundle\Entity”

我已经为一个非常有用的包 [VichUploader] 创建了一个解决方案,它缺少多个上传的功能,并且它适用于我在 [Symfony] 5.2 上创建的每个 Symfony 版本。 它在 OneToMany 关系上并且工作正常。所以我在我的自定义表单中使用了 CollectionType 和 [VichFileType] 并在我的控制器中使用了一些小技巧,这里是代码并查看所有项目,你可以在我的 GitHub 中找到它 [一个link]https://github.com/malek-laatiri

Admission.php

class Admission
{
    /**
     * @ORM\OneToMany(targetEntity=Diplome::class, mappedBy="admission")
     */
    private $diplomes;
    /**
     * @return Collection|Diplome[]
     */
    public function getDiplomes(): Collection
    {
        return $this->diplomes;
    }

    public function addDiplome(Diplome $diplome): self
    {
        if (!$this->diplomes->contains($diplome)) {
            $this->diplomes[] = $diplome;
            $diplome->setAdmission($this);
        }

        return $this;
    }

    public function removeDiplome(Diplome $diplome): self
    {
        if ($this->diplomes->removeElement($diplome)) {
            // set the owning side to null (unless already changed)
            if ($diplome->getAdmission() === $this) {
                $diplome->setAdmission(null);
            }
        }

        return $this;
    }
}

Diplome.php

<?php

namespace App\Entity;

use App\Repository\DiplomeRepository;
use Doctrine\ORM\Mapping as ORM;
use Vich\UploaderBundle\Mapping\Annotation as Vich;


/**
 * @ORM\Entity(repositoryClass=DiplomeRepository::class)
 * @Vich\Uploadable
 */
class Diplome
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\ManyToOne(targetEntity=Admission::class, inversedBy="diplomes",cascade={"persist","remove"})
     */
    private $admission;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $name;

    /**
     * @Vich\UploadableField(mapping="product_image", fileNameProperty="name")
     * @var File
     */
    private $file;

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getAdmission(): ?Admission
    {
        return $this->admission;
    }

    public function setAdmission(?Admission $admission): self
    {
        $this->admission = $admission;

        return $this;
    }

    public function getName(): ?string
    {
        return $this->name;
    }

    public function setName(string $name): self
    {
        $this->name = $name;

        return $this;
    }

    public function getFile()
    {
        return $this->file;
    }

    public function setFile( $file)
    {
        $this->file = $file;

        return $this;
    }
}

AdmissionType.php

<?php

namespace App\Form;

use App\Entity\Admission;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Vich\UploaderBundle\Form\Type\VichFileType;

class Admission1Type extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('diplomes', CollectionType::class, [
                'entry_type' => DiplomeType::class,
                'allow_add' => true,
                'allow_delete' => true,
                'required' => false,
                'label'=>false,
                'by_reference' => false,
                'disabled' => false,
            ]);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Admission::class,
        ]);
    }
}

DiplomeType.php

<?php

namespace App\Form;

use App\Entity\Diplome;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Vich\UploaderBundle\Form\Type\VichFileType;

class DiplomeType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('file',VichFileType::class)
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Diplome::class,
            "allow_extra_fields" => true,
        ]);
    }
}

_form.html.twig

<ul id="diplomes-fields-list"
    data-prototype="{{ form_widget(form.diplomes.vars.prototype)|e }}"
    data-widget-tags="{{ '<li></li>'|e }}"
    data-widget-counter="{{ form.diplomes|length }}">
    {% for emailField in form.diplomes %}
        <li>
            {{ form_errors(emailField) }}
            {{ form_widget(emailField) }}
        </li>
    {% endfor %}
</ul>
<button type="button"
        class="add-another-collection"
        data-list-selector="#diplomes-fields-list">Add another email
</button>

script.js

jQuery(document).ready(function () {
    jQuery('.add-another-collection').click(function (e) {
        var list = $("#diplomes-fields-list");
        var counter = list.data('widget-counter') | list.children().length;
        var newWidget = list.attr('data-prototype');
        newWidget = newWidget.replace(/__name__/g, counter);
        counter++;
        list.data('widget-counter', counter);

        var newElem = jQuery(list.attr('data-widget-tags')).html(newWidget);
        newElem.appendTo(list);
        newElem.append('<a href="#" class="remove-tag" style="color: darkred">remove</a>');
        $('.remove-tag').click(function(e) {
            e.preventDefault();

            $(this).parent().remove();

        });
    });
});

Controller.php

$admission = new Admission();
        $form = $this->createForm(Admission1Type::class, $admission);
        $form->handleRequest($request);
        $entityManager = $this->getDoctrine()->getManager();
        if ($form->isSubmitted() && $form->isValid()) {
            foreach ($form->getData()->getNotes() as $dip){
                $entityManager->persist($dip);
                $admission->addNote($dip);
            }
            $entityManager->persist($admission);
            $entityManager->flush();