Tag: PHP

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.

Un PHP5 toutes options pour votre Léopard

computerLa dernière version de Mac Os X, Léopard est maintenant livrée avec un couple PHP5/Apache 2 de série.

Il vous suffit d’activer le partage web pour lancer l’apache et une ligne à décommenter dans le php.ini pour bénéficier du support de PHP5 et ce sans rien faire de plus.

Cette combinaison suffit la plupart du temps, mais dès qu’il faut rajouter un module, librairie, PHP, ca devient vite compliqué. Que se soit GD ou ZIP, il est rarement simple, sans aucune recompilation d’installer ces librairies, pourtant assez classiques sur votre mac.

Et bien, un monsieur l’a compris, Marc Liyanage, qui maintient des versions de PHP5 recompilées pour mac avec toutes les options.

Pour l’installer, rien de compliqué, lancer un terminal puis si vous souhaitez faire un backup de votre version actuelle de PHP.

sudo mv /usr/local/php5 ~/Desktop/php5.old

Puis placez vous dans votre dossier de téléchargement habituel et télécharger la dernière version et dézippez là là où se trouvait l’ancienne.

wget http://www2.entropy.ch/download/php5-5.2.5-6-beta.tar.gz
tar -xzf php5-*-beta.tar.gz
sudo mv php5 /usr/local/

Il faut ensuite changer rajouter la conf de cette nouvelle version à notre apache

sudo ln -sf /usr/local/php5/entropy-php.conf /etc/apache2/other/+entropy-php.conf

Et on redémarre apache

sudo apachectl restart

Voilà, vous pouvez jeter un oeil à un phpinfo(), vous disposez maintenant de toutes les options pour votre PHP5.

Simplifiez vos conditions

accessories-text-editorLes conditions font partie intégrante de tous les langages de programmation, PHP ne déroge pas à la règle.

Cependant il n’est pas rare qu’elles gâchent la lisibilité d’un code quand elles s’imbriquent ou quand les différents états sont à plusieurs dizaines de lignes d’écart.

Un moyen simple d’y voir plus clair et de tourner vos conditions différemment.

Par exemple, on a souvent tendance à écrire:

<?php
if ($condition) {
    /* Tout mon traitement qui peut faire plusieurs dizaines de ligne */
} else {
    /* Traitement de l'erreur, par exemple */
    return false ;
}
?>

Au final, la condition n’est utilisée que pour gérer le cas d’erreur, mais celui-ci se retrouve retranché en bas de script.

Pour gagner en lisibilité, on pourrait donc écrire:

<?php
if (!$condition) {
    /* Traitement de l'erreur, par exemple */
    return false ;
}
/* Tout mon traitement qui peut faire plusieurs dizaines de ligne */
?>

La gestion de notre erreur, est maintenant dans la continuité de notre script et se révèle beaucoup plus confortable à lire. Attention toutefois, ce genre de pratique demande à ce que votre gestion d’erreur coupe l’exécution du script avec en général l’utilisation de return.

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+