Skip to content

13 juillet 2011

[Symfony] 1.4 : upload d’images dans l’admin generator

Symfony

Bonjour aux développeurs ! Et oui, les autres peuvent passer leur chemin car je doute que ce billet les intéresse.

Le but est de présenter succinctement comment gérer proprement un champ d’upload dans l’admin generator (avec doctrine).
En fait, je cherche et copie souvent ce bout de code donc autant utiliser mon blog comme marque-page et partager l’information.

Imaginons que l’on veuille créer tout simplement un slideshow en frontend.
Pour cela, il faut que le webmaster puisse charger des images qui seront chargées sur le serveur.
Voici donc notre définition doctrine pour la table gérant ces images :


Slideshow:
  actAs:
    Timestampable: ~
  columns:
    name: { type: string(255), notnull: true }
    image: { type: string(255), notnull: true }
 

En admin, le but sera donc de gérer un panel d’images auxquelles nous donnerons un nom (et qui ne servira peut-être qu’à trier/filtrer plus facilement)

Il faut à présent mettre à jour le modèle de données et les objets correspondants :


# Generation des modèles, formulaires et filtres
php ./symfony doctrine:build --all-classes
# Génération du SQL
php ./symfony doctrine:build --sql
# Cache
php ./symfony cc

Créons simplement le nouveau module de l’admin generator :


php ./symfony doctrine:generate-admin backend Slideshow

Si vous accédez à votre administration via « /backend.php/slideshow », vous afficherez votre nouveau module.
dans le schéma, nous avons défini l’image comme étant un champ texte court. Hors, nous voulons stocker sur le serveur une image (la source) et son pendant retaillée (qui sera utilisée dans le slideshow).
Il faut donc modifier l’objet « Form » afin de lui signaler que nous désirons un champ d’upload et non un champ texte.

La méthode « configure » de la classe « SlideshowForm » va donc être modifiée pour prendre en compte nos besoins


### lib/form/doctrine/SlideshowForm.class.php
class SlideshowForm extends BaseSlideshowForm
{
    public function configure()
    {
        ### Suppression des widgets spécifiques au behavior "Timestampable"
        unset($this['created_at'], $this['updated_at']);
        ### Modification du type
        $this->widgetSchema['image'] = new sfWidgetFormInputFileEditable(   array(  'label'         => 'Image',
                                                                                    'edit_mode'     => !$this->isNew(),
                                                                                    'template'      => '
%input%%delete% %delete_label%
', 'file_src' => '/uploads'.DIRECTORY_SEPARATOR.'slideshow'.DIRECTORY_SEPARATOR.$this->getObject()->getImage(), ) ); ### Modification du validateur $this->validatorSchema['image'] = new sfValidatorFile( array( 'required' => true, 'path' => sfConfig::get('sf_upload_dir').DIRECTORY_SEPARATOR.'slideshow', 'mime_types' => 'web_images', ) ); $this->validatorSchema['image_delete'] = new sfValidatorPass(); } }

Si vous testez l’upload, cela fonctionnera à merveille.
Admettons que vous souhaitiez des miniatures :

Ajoutez le plugin sfThumbnail


php ./symfony plugin:install sfThumbnailPlugin

Voici le code à ajouter dans le formulaire « SlideshowForm ».


### lib/form/doctrine/SlideshowForm.class.php
class SlideshowForm extends BaseSlideshowForm
{
    ...
    protected function processUploadedFile($oField, $sFilename = null, $aValues = null)
    {
        $mReturn = parent::processUploadedFile($oField, $sFilename, $aValues);
        if ($mReturn != "") {
            ### Si un fichier est présent dans le POST
            ### on utilise ces tableaux pour définir nos différentes dimensions voulues
            $aThumbs[] = array('dir' => '50x50',    'width' => 50,  'height' => 50);
            $aThumbs[] = array('dir' => '250x250',  'width' => 250, 'height' => 250);
            ### Suppression des anciens fichiers
            foreach ($aThumbs as $aThumb)
            {
                ### Chemin du fichier sur le serveur
                $sCurrentFile = sfConfig::get('sf_upload_dir').'/pictures/'.$aThumb['dir'].'/'. $mReturn;
                ### Si le fichier existe, il est d'abord supprimé physiquement
                if (is_file($sCurrentFile)) unlink($sCurrentFile);
            }
            ### Création des vignettes
            foreach ($aThumbs as $aThumb)
            {
                $thumbnail = new sfThumbnail($aThumb['width'],
                                             $aThumb['height'],
                                             true,
                                             false
                             );
                $thumbnail->loadFile(sfConfig::get('sf_upload_dir')."/slideshow/".$mReturn);
                $thumbnail->save(sfConfig::get('sf_upload_dir').'/slideshow/'.$aThumb['dir'].'/'.$mReturn,
                                 'image/png');
            }
        }
        return $mReturn;
    }
}

Et voila, vous avez un code fonctionnel pour ajouter des images dans votre admin generator et créer des miniatures à volonté.
Bien sur, l’image original est aussi enregistré sur le serveur. Cela peut vous sauver lorsqu’un gros changement de dimension est annoncé x semaines/mois après la mise en production.

Ces articles pourraient également vous intéresser :