Tag: upload

Symfony: Personnaliser le nom du fichier lors d’un upload avec sfWidgetFormInputFileEditable

system-software-update On emploie tous je pense, assez couramment maintenant, le widget sfWidgetFormInputFileEditable qui permet de rajouter quelques fonctionnalités à un widget d’upload classique, en l’occurrence visualisation et suppression. Le souci que j’ai rencontré récemment, c’est par contre la personnalisation du nom du fichier ainsi généré.

En effet, par défaut celui-ci est une empreinte sha1 généré aléatoirement, ce qui convient pour la majeure partie des cas, mais parfois ne suffit pas. Mais là encore Symfony étonne par le mécanisme mis en place pour contourner cette problématique, encore faut-il le savoir malheureusement.

Lire la suite

Uploadez en Symfony

accessories-text-editor Quand on utilise un framework PHP aussi propre et bien pensé que symfony, on a souvent envie de continuer ce beau travail en ajoutant notre code de la meilleur des façons pour conserver la logique de l’application, MVC, héritage, composition…

Mais ce n’est pas toujours simple. Voici un petit exemple qui concerne un passage obscur de la documentation officielle des formulaires dans symfony, l’upload de fichier.

Pour commencer, il faut souvent définir dans la définition de notre formulaire le widget et le validator correspondant. Dans notre exemple, on prendra un champ nommé avatar, imaginons un classe Profil:

public function configure()
{
    $this->widgetSchema['avatar'] = new sfWidgetFormInputFile();
    // Un upload étant rarement obligatoire, 
   // le cas de l'avatar est un bon exemple, on le rend facultatif ici
    $this->validatorSchema['avatar'] = new sfValidatorFile(array('required' => false)) ; 
}

Maintenant on a bien notre formulaire qui s’affiche correctement. Le problème, si on n’upload pas de nouvel avatar, à la prochaine sauvegarde, le champ avatar sera remis à sa valeur par défaut, fonctionnement tout à fait normal en l’état.
Pour éviter ceci, voici la fonction à rajouter, toujours dans notre classe de notre formulaire Profil, c’est en fait une surcharge de la méthode save:

public function save($con = null)
{
    // On test si le champ avatar a été renseigné dans le formulaire
    if ($file = $this->getValue('avatar'))
    {
      // Si oui, on sauvegarde le fichier
      $filename = 'nomDuFichier';
      $extension = $file->getExtension($file->getOriginalExtension());
      $file->save(sfConfig::get('sf_upload_dir').$filename.$extension);
    }
    else
    {
      // Si non, on récupère la version actuelle dans l'objet Père (ici profil), 
      // que l'on insère dans le tableau de valeur du formulaire
      $this->values['avatar'] = $this->getObject()->getAvatar();
    }
 
    // Puis on lance la sauvegarde normal de la classe mère
    return parent::save($con);
}

Et voilà, nous sommes restés dans la logique métier de symfony, en surchargeant l’existant et surtout en permettant de garder notre action identique, les modifications ayant été apportées dans le modèle.

PHVsPjxsaT48c3Ryb25nPndvb19hZHNfcm90YXRlPC9zdHJvbmc+IC0gdHJ1ZTwvbGk+PGxpPjxzdHJvbmc+d29vX2FkX2ltYWdlXzE8L3N0cm9uZz4gLSBodHRwOi8vd3d3Lndvb3RoZW1lcy5jb20vYWRzL3dvb3RoZW1lcy0xMjV4MTI1LTEuZ2lmPC9saT48bGk+PHN0cm9uZz53b29fYWRfaW1hZ2VfMjwvc3Ryb25nPiAtIGh0dHA6Ly93d3cud29vdGhlbWVzLmNvbS9hZHMvd29vdGhlbWVzLTEyNXgxMjUtMi5naWY8L2xpPjxsaT48c3Ryb25nPndvb19hZF9pbWFnZV8zPC9zdHJvbmc+IC0gaHR0cDovL3d3dy53b290aGVtZXMuY29tL2Fkcy93b290aGVtZXMtMTI1eDEyNS0zLmdpZjwvbGk+PGxpPjxzdHJvbmc+d29vX2FkX2ltYWdlXzQ8L3N0cm9uZz4gLSBodHRwOi8vd3d3Lndvb3RoZW1lcy5jb20vYWRzL3dvb3RoZW1lcy0xMjV4MTI1LTQuZ2lmPC9saT48bGk+PHN0cm9uZz53b29fYWRfdXJsXzE8L3N0cm9uZz4gLSBodHRwOi8vd3d3Lndvb3RoZW1lcy5jb208L2xpPjxsaT48c3Ryb25nPndvb19hZF91cmxfMjwvc3Ryb25nPiAtIGh0dHA6Ly93d3cud29vdGhlbWVzLmNvbTwvbGk+PGxpPjxzdHJvbmc+d29vX2FkX3VybF8zPC9zdHJvbmc+IC0gaHR0cDovL3d3dy53b290aGVtZXMuY29tPC9saT48bGk+PHN0cm9uZz53b29fYWRfdXJsXzQ8L3N0cm9uZz4gLSBodHRwOi8vd3d3Lndvb3RoZW1lcy5jb208L2xpPjxsaT48c3Ryb25nPndvb19hbHRfc3R5bGVzaGVldDwvc3Ryb25nPiAtIGN1c3RvbS5jc3M8L2xpPjxsaT48c3Ryb25nPndvb19hdXRvX2ltZzwvc3Ryb25nPiAtIGZhbHNlPC9saT48bGk+PHN0cm9uZz53b29fY29udGVudF9hcmNoaXZlczwvc3Ryb25nPiAtIGZhbHNlPC9saT48bGk+PHN0cm9uZz53b29fY29udGVudF9ob21lPC9zdHJvbmc+IC0gZmFsc2U8L2xpPjxsaT48c3Ryb25nPndvb19jdXN0b21fZmF2aWNvbjwvc3Ryb25nPiAtIDwvbGk+PGxpPjxzdHJvbmc+d29vX2ZlZWRidXJuZXJfdXJsPC9zdHJvbmc+IC0gPC9saT48bGk+PHN0cm9uZz53b29fZ29vZ2xlX2FuYWx5dGljczwvc3Ryb25nPiAtIDwvbGk+PGxpPjxzdHJvbmc+d29vX2xvZ288L3N0cm9uZz4gLSBodHRwOi8vd3d3LmFtaWNhbGVtZW50LXdlYi5uZXQvd3AtY29udGVudC93b29fdXBsb2Fkcy8zLWxvZ28ucG5nPC9saT48bGk+PHN0cm9uZz53b29fbWFudWFsPC9zdHJvbmc+IC0gaHR0cDovL3d3dy53b290aGVtZXMuY29tLzwvbGk+PGxpPjxzdHJvbmc+d29vX25hdl9leGNsdWRlPC9zdHJvbmc+IC0gPC9saT48bGk+PHN0cm9uZz53b29fcmVzaXplPC9zdHJvbmc+IC0gdHJ1ZTwvbGk+PGxpPjxzdHJvbmc+d29vX3Nob3J0bmFtZTwvc3Ryb25nPiAtIHdvbzwvbGk+PGxpPjxzdHJvbmc+d29vX3RoZW1lbmFtZTwvc3Ryb25nPiAtIFR5cGViYXNlZDwvbGk+PGxpPjxzdHJvbmc+d29vX3RodW1iX2hlaWdodDwvc3Ryb25nPiAtIDEwMDwvbGk+PGxpPjxzdHJvbmc+d29vX3RodW1iX3dpZHRoPC9zdHJvbmc+IC0gMTAwPC9saT48bGk+PHN0cm9uZz53b29fdXBsb2Fkczwvc3Ryb25nPiAtIGh0dHA6Ly93d3cuYW1pY2FsZW1lbnQtd2ViLm5ldC93cC1jb250ZW50L3dvb191cGxvYWRzLzMtbG9nby5wbmc8L2xpPjwvdWw+