Search code examples
symfonyvichuploaderbundleformcollection

Vich upload, multi upload images doesn't work


I'm trying to upload multi images using vich upload bundle and symfony 5 :

I created a one to many relation between User and Images :

/**
 * @ORM\Entity(repositoryClass=UserRepository::class)
 * @UniqueEntity(fields={"email"}, message="There is already an account with this email")
 */
class User implements UserInterface
{

...

/**
 * @ORM\OneToMany(targetEntity=Images::class, mappedBy="owner", cascade={"persist"})
 */
private $images;

 public function __construct()
{
    ...
    $this->images = new ArrayCollection();
}

...

/**
 * @return Collection|Images[]
 */
public function getImages(): Collection
{
    return $this->images;
}

public function addImage(Images $image): self
{
    if (!$this->images->contains($image)) {
        $this->images[] = $image;
        $image->setOwner($this);
    }

    return $this;
}

public function removeImage(Images $image): self
{
    if ($this->images->removeElement($image)) {
        // set the owning side to null (unless already changed)
        if ($image->getOwner() === $this) {
            $image->setOwner(null);
        }
    }

    return $this;
}

My Images entity is vich uploadable :

/**
 * @ORM\Entity(repositoryClass=ImagesRepository::class)
 * @Vich\Uploadable
 */
class Images
{
    
     ..

    /**
     * @Vich\UploadableField(mapping="user_images", fileNameProperty="imageName", size="imageSize")
     * @var File|null
     */
    private $imageFile;

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

    /**
     * @ORM\Column(type="integer")
     *
     * @var int|null
     */
    private $imageSize;

    /**
     * @ORM\Column(type="datetime")
     *
     * @var \DateTimeInterface|null
     */
    private $updatedAt;

    

    public function getImageFile(): ?File
    {
        return $this->imageFile;
    }

    /**
     * @param File|UploadedFile|null $imageFile
     */
    public function setImageFile(?File $imageFile = null): void
    {
        $this->imageFile = $imageFile;

        if (null !== $imageFile) {
            // It is required that at least one field changes if you are using doctrine
            // otherwise the event listeners won't be called and the file is lost
            $this->updatedAt = new \DateTimeImmutable();
        }
    }

    public function getImageName(): ?string
    {
        return $this->imageName;
    }

    public function setImageName(?string $imageName): void
    {
        $this->imageName = $imageName;
    }

    public function getImageSize(): ?int
    {
        return $this->imageSize;
    }

    public function setImageSize(?int $imageSize): void
    {
        $this->imageSize = $imageSize;
    }

    public function getUpdatedAt(): ?\DateTimeInterface
    {
        return $this->updatedAt;
    }

    public function setUpdatedAt(\DateTimeInterface $updatedAt): self
    {
        $this->updatedAt = $updatedAt;

        return $this;
    }
}

In UserType i added :

  ->add(
                'images',
                CollectionType::class,
                array(
                    'entry_type' => ImagesType::class,
                    'allow_add'    => true,
                    'allow_delete' => true,
                )
            )

in my ImagesType : ->add( 'imageFile', FileType::class ) ;

And Finally in my user form twig :

 <div class="form-group">
                                    <div class="custom-file">
                                        {{  form_widget(form.images, { 'attr' : { 'class' : 'custom-file-input' } })  }}
                                        {{ form_label(form.images, 'Choose images', {'label_attr': {'class': 'custom-file-label'}}) }}
                                    </div>
                                </div>
                            </div>

i got the input like this but it's not working :

enter image description here


Solution

  • You should use VichFileType type instead of FileType type like said in the bundle docs : https://github.com/dustin10/VichUploaderBundle/blob/master/docs/form/vich_file_type.md

    Code Sample ( from the docs ):

    use Vich\UploaderBundle\Form\Type\VichFileType;
    
    class Form extends AbstractType
    {
        public function buildForm(FormBuilderInterface $builder, array $options): void
        {
            // ...
    
            $builder->add('genericFile', VichFileType::class, [
                'required' => false,
                'allow_delete' => true,
                'delete_label' => '...',
                'download_uri' => '...',
                'download_label' => '...',
                'asset_helper' => true,
            ]);
        }
    }
    

    That's part of the solutions, now images is a collection, so you need to have a collection of VichFileType: https://symfony.com/doc/current/form/form_collections.html