Symfony 1.4 : Upload d’image sans dupliquer les fichiers

Benjamin Longearet 21 février 2010 2
Symfony 1.4 : Upload d’image sans dupliquer les fichiers

Bon la gestion des formulaires nous apportent des fonctionnalités impressionnantes avec les widgets et les validators. Mais en m’amusant sur mon backend, j’ai réalisé que chaque changement d’une photo, provoqué la création d’une nouvelle image et non le remplacement.

Je vais donc vous expliquer comment télécharger/uploader des images proprement sous symfony en évitant la redondance et la duplication.

Le formulaire

Les premières modifications vont s’effectuer dans le fichier de notre formulaire. Pour l’exemple je vais prendre le formulaire du modèle Profile créé dans un autre tutoriel (voir ici).

On ouvre donc le fichier /lib/form/doctrine/ProfileForm.php. On va venir insérer le code suivant dans la fonction configure.

        $this->widgetSchema['photo'] = new sfWidgetFormInputFileEditable(array(
                        // Label qui sera affiché
                        'label'        => "Photo utilisateur",
                        // Lien de la photo à afficher
                        'file_src'     => $this->getObject()->getPhotoFileSrc(),
                        // à vrai
                        'is_image'     => true,
                        // on modifie que si l'image existe
                        'edit_mode'    => !$this->isNew(),
                        // active l'option de suppression
                        'with_delete'  => true
        ));
        $this->validatorSchema['photo'] = new sfValidatorFile(array(
                        // Définit si le champs est obligatoire ou non
                        'required'   => false,
                        // Le chemin où la photo sera uploadé
                        'path'       => $this->getObject()->getPhotoDirPath(),
                        'mime_types' => 'web_images',
        ));
        $this->validatorSchema['photo_delete'] = new sfValidatorPass();

Alors, que je vous explique un petit peu quand même!

  • Les widgets permettent de configurer les éléments HTML (plus d’infos sur le site de symfony),
  • Les validators servent à la validations des données du formulaire (plus d’infos sur le site de symfony).

Nous avons mis en place l’aspect HTML et les validateurs en place, passons maintenant au modèle.

Le modèle

Nous allons surcharger la méthode generateVotreNomDeChampFilename et implémenter quelques méthodes pour nous faciliter la vie sur les chemins de notre image.

Dans un premier temps, voici les méthodes de gestion du chemin et de l’adresse de l’image:

 public function getPhotoFileSrc() {
         if (!$this->getPhoto())
                 // utiliser ce champs pour afficher une image par défaut dans le formulaire
                 // return null;
                 return '/images/avatar.gif';
         return  $this->getPhotoDirSrc() . '/' . $this->getPhoto();
 }
 public function getPhotoFilePath() {
         if (!$this->getPhoto())
                 return null;
         return  $this->getPhotoDirPath() . '/' . $this->getPhoto();
 }
 public function getPhotoDirSrc() {
         return '/uploads/user_photo';
 }
 public function getPhotoDirPath() {
         return sfConfig::get('sf_upload_dir') . '/user_photo';
 }

Je me répète, mais vous pouvez faire sans ces fonctions, elles sont là pour facilité la gestion du chemin et de l’adresse de l’image.

Ensuite voici la surcharge de la méthode generateVotreNomDeChampFilename

public function generatePhotoFilename(sfValidatedFile $validator) {
        $path = split('/', $validator->getPath());
        $filenameBase = md5($this->getSfGuardUserId().$path[(sizeof($path)-1)]);
        if (!file_exists($validator->getPath().'/'.$validator->getOriginalName())) {
            return $filenameBase.$validator->getOriginalExtension();
        }
        $i = 1;
        while (1) {
            $newFilename = sprintf('%s-%s.%s', basename($filenameBase), $i, $validator->getOriginalExtension());
            if (!file_exists($validator->getPath().'/'.$newFilename)) {
                return $newFilename;
            }
            $i++;
        }
    }

A la ligne 3, vous pouvez mettre ce que vous voulez, il faut penser que le nom soit unique à chaque utilisateur (d’où la raison d’utiliser $this->getSfGuardUserId() qui est unique).

Voilà vous pouvez vous rendre sur votre application backend et tester le résultat! Plus de duplication des images dans le fichier /web/uploads/.

Bon dév’ :D

Geekos.fr vous recommande les articles suivants

2 Commentaires »

  1. Yann 21 février 2012 au 16 h 07 min - Reply

    Bonjour et merci pour cet article vraiment très clair et bien écrit.

    Bon courage et bonne continuation ;)

Laissez un message »