Tuto Symfony 3 :Upload d'une image en utilisant un service Upload File
La fonctionnalité Upload est très courante et incontournable pour un site dynamique .Afin de faciliter son développement Symfony 3 offre la possibilité d'utiliser un service afin d'optimiser le code et de pouvoir réutiliser le service plusieurs fois dans différents contrôleur.Dans ce tutoriel nous allons ajouter le champ image au formulaire d'ajout d'un plat.Cet exemple est applicable sur les fichier pdf aussi et d’autres format il faut juster adapter quelque propriétés.
l'option mimeTypes sert à préciser le type de fichier accepté dans notre cas nous demandons une image de format jpeg mais vous pouvez notamment ajouter d'autres formats .Si vous avez besoin d'ajouter un fichier pdf vous devez remplacer "image/jpeg" par "application/pdf"
visitez ce lien pour voir les mimeTypes des autre formats utilisables:
https://www.sitepoint.com/mime-types-complete-list/
Si votre version de php n'est pas récente 5.5 par exemple, ce code ne fonctionnera pas, dans ce cas ajoutez le champ image comme ceci:
Il faut aussi modifer le fichier twig afin d'afficher le nouveau champ .
Si vous afficher votre formulaire de cette façon
vous n'avez pas besoin de modifier le fichier ajoutPlat.html.twig.
1-Ajouter un attribut image
La première chose à faire est d'ajouter un attribut image à l'entité Plat.Le type de cet attribut est String car il sert à contenir le nom du fichier image et non pas l'image .Ce nom nous permettra après d’accéder à l'image téléchargée.
<?php namespace RestoBundle\Entity; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; //.... /** * @ORM\Column(type="string") * * @Assert\NotBlank(message="Ajouter une image jpg") * @Assert\File(mimeTypes={ "image/jpeg" }) */ private $image; public function getImage() { return $this->image; } public function setImage($image) { $this->image = $image; return $this; } ?>
l'option mimeTypes sert à préciser le type de fichier accepté dans notre cas nous demandons une image de format jpeg mais vous pouvez notamment ajouter d'autres formats .Si vous avez besoin d'ajouter un fichier pdf vous devez remplacer "image/jpeg" par "application/pdf"
visitez ce lien pour voir les mimeTypes des autre formats utilisables:
https://www.sitepoint.com/mime-types-complete-list/
2-Ajouter un champs image au formulaire
Afin d'afficher un champ pour ajouter une image il faut mettre le fichier PlatType.php à jour .<?php namespace RestoBundle\Form; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\Form\Extension\Core\Type\FileType; class PlatType extends AbstractType { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder // ... ->add('image', FileType::class, array('label' => 'Image(JPG)')) // ... ; } ?>
Si votre version de php n'est pas récente 5.5 par exemple, ce code ne fonctionnera pas, dans ce cas ajoutez le champ image comme ceci:
<?php namespace RestoBundle\Form; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; class PlatType extends AbstractType { /** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder //.. ->add('image', 'Symfony\Component\Form\Extension\Core\Type\FileType', array('label' => 'Image')) //.. ; } ?>
Il faut aussi modifer le fichier twig afin d'afficher le nouveau champ .
{{ form_start(form) }}
{# ... #}
{{ form_row(form.image) }}
{{ form_end(form) }}
Si vous afficher votre formulaire de cette façon
{{form_start(form)}} {{form_widget(form)}} <input class="btn btn-success" type="submit" value="Ajouter" /> {{form_end(form)}}
vous n'avez pas besoin de modifier le fichier ajoutPlat.html.twig.
3-Créer le service d'upload
Sous le répertoire RestoBundle , on créé un nouveau fichier ImageUpload.php.<?php namespace RestoBundle; use Symfony\Component\HttpFoundation\File\UploadedFile; class ImageUpload { private $targetDir; public function __construct($targetDir) { $this->targetDir = $targetDir; } public function upload(UploadedFile $file) { $fileName = md5(uniqid()).'.'.$file->guessExtension(); $file->move($this->getTargetDir(), $fileName); return $fileName; } public function getTargetDir() { return $this->targetDir; } }
* Lorsque le
formulaire est téléchargé, l’attribut image contient tout le contenu du fichier
jpg . Étant donné que cet attribut ne stocke que le nom du fichier, vous devez
définir sa nouvelle valeur avant de persister les changements de l'entité;
* Dans les
applications Symfony, les fichiers téléchargés sont des objets de la classe
UploadedFile. Cette classe fournit des méthodes pour les opérations sur les
fichiers téléchargés;
* La classe UploadedFile fournit des
méthodes pour obtenir l'extension de fichier d'origine (getExtension ()), la
taille de fichier d'origine (getClientSize ()) et le nom de fichier d'origine
(getClientOriginalName ()).
4-Enregistre le service dans le fichier services.yml
# app/config/services.yml //... resto.image_uploader: class: RestoBundle\ImageUpload arguments: ['%images_directory%']
5-Définir Images_directory
Créez le répertoire dans lequel vous voulez mettre le images téléchargées sous le dossier web/ par exemple uploads/images .ensuite vous devez déclarer le paramètre images_directory en luit attribuant le chemin de ce dossier.# app/config/config.yml //... parameters: locale: en images_directory: '%kernel.root_dir%/../web/uploads/images'
6-Synchronisation en utilisant Doctrine Listener
Vous pouvez utiliser le service uploadImage à partir du contrôleur sans avoir besoin des d'un listener si vous n'avez pas besoin d'ajouter un élément à la base de données .Mais dans notre cas nous voulons ajouter un nouveau plat dans la table plat de la BDD .Doctrine Listener accomplit donc le rôle de synchronisation . Créez un dossier EventListener sous le répertoire RestoBundle. Ensuite créez une classe UploadImageListener
<?php namespace RestoBundle\EventListener; use Symfony\Component\HttpFoundation\File\UploadedFile; use Doctrine\ORM\Event\LifecycleEventArgs; use Doctrine\ORM\Event\PreUpdateEventArgs; use RestoBundle\Entity\Plat; use RestoBundle\ImageUpload; class ImageUploadListener { private $uploader; public function __construct(ImageUpload $uploader) { $this->uploader = $uploader; } public function prePersist(LifecycleEventArgs $args) { $entity = $args->getEntity(); $this->uploadFile($entity); } public function preUpdate(PreUpdateEventArgs $args) { $entity = $args->getEntity(); $this->uploadFile($entity); } private function uploadFile($entity) { // upload only works for Product entities if (!$entity instanceof Plat) { return; } $file = $entity->getImage(); // only upload new files if (!$file instanceof UploadedFile) { return; } $fileName = $this->uploader->upload($file); $entity->setImage($fileName); } }
Déclarez le listener dans le fichier services.yml
# app/config/services.yml //... resto.doctrine_image_listener: class: RestoBundle\EventListener\ImageUploadListener arguments: ['@resto.image_uploader'] tags: - { name: doctrine.event_listener, event: prePersist } - { name: doctrine.event_listener, event: preUpdate }6-Afficher l'image ajouté
¨Enfin Pour afficher une image vous devez définir le chemin src , dans notre il faut définir l’attribut src comme ceci:
<img src="{{ asset('uploads/images/' ~ plat.image) }}" height="100px" width="250px">
Commentaires
Enregistrer un commentaire