Skip to content
Advertisement

VichUploaderBundle in Symfony 6

I hope you can help me because i’m searching and i’m lost 🙁

I’m trying to upload image in my symfony 6 project with VichUploaderBundle.

I used the doc : https://github.com/dustin10/VichUploaderBundle/blob/master/docs/usage.md#step-1-configure-an-upload-mapping

But i have this error :

The class “AppEntityClient” is not uploadable. If you use annotations to configure VichUploaderBundle, you probably just forgot to add @VichUploadable on top of your entity. If you don’t use annotations, check that the configuration files are in the right place. In both cases, clearing the cache can also solve the issue.

My vich_uploader.yaml :

vich_uploader:
    db_driver: orm


    mappings:
       clients_logo:
           uri_prefix: '%client_logo%'
           upload_destination: '%kernel.project_dir%/public%client_logo%'
           namer: VichUploaderBundleNamingSmartUniqueNamer

My Client Entity :

<?php

namespace AppEntity;

use DoctrineORMMapping as ORM;
use AppRepositoryClientRepository;
use DoctrineCommonCollectionsCollection;
use SymfonyComponentHttpFoundationFileFile;
use DoctrineCommonCollectionsArrayCollection;
use VichUploaderBundleMappingAnnotation as Vich;

#[ORMEntity(repositoryClass: ClientRepository::class)]
#[VichUploadable]
class Client
{
    #[ORMId]
    #[ORMGeneratedValue]
    #[ORMColumn(type: 'integer')]
    private $id;

    #[ORMColumn(type: 'integer')]
    private $numero_client;

    /**
    * Some fields
    */

    /**
     * NOTE: This is not a mapped field of entity metadata, just a simple property.
     */
    #[VichUploadableField(mapping: 'clients_logo', fileNameProperty: 'logo')]
    private ?File $imageFile = null;

    #[ORMColumn(type: 'string', length: 255, nullable: true)]
    private $logo;


    #[ORMColumn(type: 'datetime', nullable: true)]
    private ?DateTimeInterface $updatedAt = null;

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

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

    public function getLogo(): ?string
    {
        return $this->logo;
    }

    public function setLogo(?string $logo): self
    {
        $this->logo = $logo;

        return $this;
    }

    /**
     * If manually uploading a file (i.e. not using Symfony Form) ensure an instance
     * of 'UploadedFile' is injected into this setter to trigger the update. If this
     * bundle's configuration parameter 'inject_on_load' is set to 'true' this setter
     * must be able to accept an instance of 'File' as the bundle will inject one here
     * during Doctrine hydration.
     *
     * @param File|SymfonyComponentHttpFoundationFileUploadedFile|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 getImageFile(): ?File
    {
        return $this->imageFile;
    }

    public function getBddClient(): ?BaseClient
    {
        return $this->bdd_client;
    }

    public function setBddClient(?BaseClient $bdd_client): self
    {
        $this->bdd_client = $bdd_client;

        return $this;
    }

    /**
     * @return Collection<int, Applis>
     */
    public function getApplis(): Collection
    {
        return $this->applis;
    }

    public function addAppli(Applis $appli): self
    {
        if (!$this->applis->contains($appli)) {
            $this->applis[] = $appli;
        }

        return $this;
    }

    public function removeAppli(Applis $appli): self
    {
        $this->applis->removeElement($appli);

        return $this;
    }

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

    public function setUpdateAt(): self
    {
        $this->updatedAt = new DateTimeImmutable();

        return $this;
    }
}

My FormType :

<?php

namespace AppForm;

use AppEntityClient;
use SymfonyComponentFormAbstractType;
use SymfonyComponentFormCallbackTransformer;
use SymfonyComponentFormFormBuilderInterface;
use VichUploaderBundleFormTypeVichImageType;
use SymfonyComponentValidatorConstraintsFile;
use SymfonyComponentOptionsResolverOptionsResolver;
use SymfonyComponentFormExtensionCoreTypeDateType;
use SymfonyComponentFormExtensionCoreTypeFileType;
use SymfonyComponentFormExtensionCoreTypeTextType;
use SymfonyComponentFormExtensionCoreTypeEmailType;
use SymfonyComponentFormExtensionCoreTypeChoiceType;

class ClientType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('nom', TextType::class, [
                'label' => false,
            ])
            //Some add fields
            ->add('imageFile', VichImageType::class, [
                'required' => false
            ]);

        //Indispensable pour faire fonctionner le select du formulaire sinon erreur 500
        $builder->get('type_contrat')
            ->addModelTransformer(new CallbackTransformer(
                function ($typeContratArray) {
                    // transform the array to a string
                    return count($typeContratArray) ? $typeContratArray[0] : null;
                },
                function ($typeContratString) {
                    // transform the string back to an array
                    return [$typeContratString];
                }
            ));
    }

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

In my form twig :

<div class="col-md-6">
    {{ form_row(form.imageFile, { 
        label: 'Logo',
        'attr': {'class': 'form-control'}
    }) }}
</div>

Anybody can explain what’s going on ? 🙁

Advertisement

Answer

Assuming you are using Php 8+ configure the bundle to use attributes instead of annotations

vich_uploader:
    metadata:
        type: attribute

ref docs

User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement