Installation et l'utilisation du composant Vich Uploader pour l'upload de fichiers
Objectifs
Apprendre à installer et configurer le composant Vich Uploader
Apprendre à utiliser le composant Vich Uploader pour téléverser un fichier
Rappel :
Nous venons de voir comment mettre en place un téléversement de fichier avec les formulaires de Symfony. L'exemple était de donner la possibilité de rattacher une photo à un produit.
Maintenant, nous allons voir comment intégrer un composant de téléchargement de fichier qui va nous permettre de :
Simplifier et uniformiser le processus de téléchargement de fichier,
Ne pas coder tout le processus de sauvegarde.
Contexte :
Dans le contexte d'une pratique professionnelle, vous utiliserez la notion d'upload de fichier dans le cas où vous aurez besoin de donner la possibilité de présenter une description autre que du texte (image, pdf, etc.), de stocker les fichiers sur le serveur et en base de données.
Dans cette partie, nous allons associer une image à une fiche produit grâce au composant VichUploader, afin de donner un visuel plus attractif du produit. Le fichier sera stocké sur le serveur et son nom sera mis en base de données en tant que propriété du produit.
Commençons par installer et configurer le composant de VichUploader.
Méthode :
Pour installer le composant VichUploader, nous allons utiliser Composer, le gestionnaire de composants PHP.
Le nom du composant : vich/uploader-bundle
À la racine du projet où se trouve le fichier « composer.json », exécuter la commande « require » et répondre par « yes » à la fin de l'installation, pour que le composant puisse créer les fichiers nécessaires au bon fonctionnement de VichUploader.
> composer require vich/uploader-bundle
Nous devons mettre en place la configuration minimale pour que le composant puisse fonctionner.
Méthode :
Ajoutons dans le fichier ./config/packages/vich_uploader.yaml, la configuration du driver de la base de données avec l'ORM.
# config/packages/vich_uploader.yaml
vich_uploader
db_driver orm
Avant de télécharger des fichiers, nous devons configurer les mappings pour le VichUploaderBundle.
Ces mappings indiquent au composant où les fichiers doivent être téléchargés et quels chemins doivent être utilisés pour les afficher dans l'application.
Dans le fichier config/services.yaml, on doit spécifier le chemin du répertoire des fichiers téléversés.
# config/services.yaml
parameters
app.path.produit_images /uploads/images/produits
Dans le fichier config/packages/vich_uploader.yaml, on spécifie la configuration du mapping.
# config/packages/vich_uploader.yaml
vich_uploader
# ...
mappings
produit_images
uri_prefix'%app.path.produit_images%'
upload_destination'%kernel.project_dir%/public%app.path.produit_images%'
La valeur mapping produit_images est un nom librement choisi qui contient la configuration pour un mapping spécifique.
Cette valeur sera utilisée ultérieurement dans la configuration de l'entité.
Les images téléchargées sont stockées dans le répertoire défini dans upload_destination.
Complément :
L'option uri_prefix définit l'url permettant d'accéder aux fichiers depuis le site.
Conseil :
N'hésitez pas à créer autant de mapping que de cas d'utilisation (Ex : photo d'utilisateur).
Maintenant que le composant VichUploader est configuré, préparons notre entité produit pour conserver les images.
Méthode :
Récupérons notre entité Produit :
La première modification que nous devons apporter consiste à ajouter l'annotation téléchargeable à la classe d'entité grâce à cette annotation : @Vich\Uploadable.
Exemple : Code
**
* @ORM\Entity(repositoryClass=ProduitRepository::class)
* @Vich\Uploadable
*/
class Produit
{
// ...
}
Méthode :
Ensuite, nous avons besoin de 2 nouvelles propriétés “image” et “fichierImage" et nous rajoutons aussi une propriété date de dernière mise à jour qui permettra à vichupdater de gérer l'enregistrement des fichiers.
Exemple : Code
namespace App\Entity;
// ...
use Symfony\Component\HttpFoundation\File\File;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
/**
* @ORM\Entity(repositoryClass=ProduitRepository::class)
* @Vich\Uploadable
*/
class Produit
{
// ...
/**
* @ORM\Column(type="string", length=255, nullable=true)
* @var string
*/
private $image;
/**
* @Vich\UploadableField(mapping="produit_images", fileNameProperty="image")
* @var File
*/
private $fichierImage;
// Default car nous avons déjà des produits
/**
* @ORM\Column(type="datetime", options={"default": "CURRENT_TIMESTAMP"})
* @var \DateTime
*/
private $mis_a_jour_le;
/**
* @return null|string
*/
public function getImage(): ?string
{
return $this->image;
}
/**
* @param null|string $image
*/
public function setImage(?string $image = null): void
{
$this->image = $image;
}
/**
* @return null|File
*/
public function getFichierImage(): ?File
{
return $this->fichierImage;
}
/**
* @param File|null $fichierImage
*/
public function setFichierImage(?File $fichierImage = null): void
{
$this->fichierImage = $fichierImage;
if ($fichierImage) {
$this->mis_a_jour_le = new \DateTime('now');
}
}
// ...
}
Attention :
Il est nécessaire qu'au moins un champ change si nous utilisons Doctrine. Sinon, les écouteurs d'événements ne seront pas appelés et le fichier sera perdu. C'est pourquoi nous avons ajouté le champ « mis_a_jour ».
Définition :
La propriété image stocke uniquement le nom de l'image importée et elle est conservée dans la base de données.
La propriété fichierImage stocke le contenu binaire du fichier image et elle n'est pas conservée dans la base de données (c'est pourquoi elle ne définit pas d'annotation @ORM). Elle doit définir une annotation @Vich\UploadableField
qui va permettre de :
Configurer la gestion du téléversement du contenu binaire dans un fichier. Ce fichier sera stocké dans un répertoire spécifié dans le mapping configuré dans le fichier
config/packages/vich_uploader.yaml
.Enregistrer le nom du fichier dans une propriété de l'entité.
Cette annotation prend en paramètre la clé de mapping à utiliser (dans ce cas : « produit_images ») et le nom de la propriété de l'entité qui stockera le nom de l'image en base de données (dans ce cas : « image »).
Nous devons mettre à jour le schéma de la base de données avec les nouvelles propriétés de produit.
Méthode :
Exécutons la commande de doctrine.
> php bin/console doctrine:schema:update --force
Utilisons enfin notre composant VichUploader, en ajoutant dans la construction du formulaire de création de Produit de Symfony la form de type Vich\UploaderBundle\Form\Type\VichFileType.
Exemple : Code
<?php
namespace App\Form\Type;
// ...
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Vich\UploaderBundle\Form\Type\VichFileType;
class ProduitType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
// ..............
->add('fichierImage', VichFileType::class)
;
}
}
Remarque :
Maintenant que nous venons de mettre en place l'upload avec le composant VichUploader, nous devrions retrouver la même interface de création de produit de la première partie du cours.
Après avoir enregistré les images des produits, nous allons terminer par afficher l'image dans la liste des produits.
Méthode :
Pour afficher l'url du produit depuis Twig, nous pouvons utiliser la fonction « vich_uploader_asset », qui prend en paramètre l'objet concerné et le nom de la propriété qui stocke les données binaires des fichiers.
Exemple : Code
Dans notre exemple, nous aurons « produit » comme objet entité produit et « fichierImage » comme propriété qui stocke les données binaires.
{% for produit in produits %}{% if produit.getImage() %} <img src="{{ vich_uploader_asset(produit, 'fichierImage') }}"> {% endif %}