Petit tuto pour installer le bundle vich/uploader-bunder qui permet d’ajouter la gestion d’upload de fichier dans un projet symfony 5.

Nous ajoutons la notion d’image à l’entité nommée « person », notons que dans le cas ci-dessous, notre projet tourne avec des containers docker : ngnix, php, mysql.

Installation du bundle

N’oubliez surtout pas de vous positionner dans le container php pour ne pas interférer avec la version php de votre système local.

$ docker exec -it arbre_php sh

Une fois dans le container vous pouvez procéder à l’installation du bundle via composer.

# composer require vich/uploader-bundle

Paramétrage du bundle

Ajouter le fichier vich_uploader.yaml dans /config/packages

vich_uploader:
  db_driver: orm
  mappings:
    person_images:
      uri_prefix:         '%app.path.person_images%'
      upload_destination: '%kernel.project_dir%/public%app.path.person_images%'

Dans le fichier services.yaml on ajoute le paramètre suivant :

parameters:
    app.path.person_images: /uploads/images/person

Votre entité

Dans l’entité « person », on injecte les dépendances et on ajoute l’annotation

use Symfony\Component\HttpFoundation\File\File;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
/**
 * @ORM\Entity
 * @Vich\Uploadable
 */

Ajout des getter et setter (accesseurs)
/**
     * @ORM\Column(type="string", length=255)
     * @var string
     */
    private $image;

    /**
     * @Vich\UploadableField(mapping="product_images", fileNameProperty="image")
     * @var File
     */
    private $imageFile;

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

    // ...

    public function setImageFile(File $image = null)
    {
        $this->imageFile = $image;

        // VERY IMPORTANT:
        // 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
        if ($image) {
            // if 'updatedAt' is not defined in your entity, use another property
            $this->updatedAt = new \DateTime('now');
        }
    }

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

    public function setImage($image)
    {
        $this->image = $image;
    }

    public function getImage()
    {
        return $this->image;
    }

Premières erreurs rencontrées !

Je tente juste l’accès au front :

ERREUR : There is no extension able to load the configuration for « vich_uploader »

Dans config/bunddle.yaml, il faut ajouter

Vich\UploaderBundle\VichUploaderBundle :: class => [‘all’ => true],

make:migration doctrine:migration:migrate

ERREUR : Invalid datetime format: 1292 Incorrect datetime value: ‘0000-00-00 00:00:00’ for column ‘updated_at’ at row 1

Migration xxx failed during Execution. Error An exception occurred while executing ‘ALTER TABLE person ADD image VARCHAR(255) NOT NULL, ADD updated_at DATETIME NOT NULL’:

SQLSTATE[22007]: Invalid datetime format: 1292 Incorrect datetime value: ‘0000-00-00 00:00:00’ for column ‘updated_at’ at row 1

Il manque une valeur par défaut ! Pour corriger le problème, dans les annotations de la propriété, on accepte la valeur nul.

", nullable=true"

La migration passe mieux 😉

Ajout du champ dans votre formulaire

->add('imageFile', VichImageType::class)

Ajout de l’image dans le template TWIG

<img src="{{ vich_uploader_asset(person, 'imageFile') }}" width="50px">

Si vous faites une erreur dans l’appel vous aurez l’erreur suivante :
An exception has been thrown during the rendering of a template (« Impossible to determine the class name. Either specify it explicitly or give an object »).