Developpez.com

Le Club des Développeurs et IT Pro

PHP intègre désormais le bloc "Finally"

Pour une gestion plus propre des sorties d'exceptions

Le 2012-08-16 13:41:23, par tarikbenmerar, Chroniqueur Actualités
Xinchen Hui, développeur du projet PHP, a commité hier l'introduction du mot clé "finally" dans le corps du langage.

Cette fonctionnalité, à mainte reprise sollicitée par la communauté, vient d'être officiellement intégrée au langage après un vote favorable ce lundi. Sa RFC (demande de commentaires) a reçu 25 oui (dont celui de Rasmus Lerdorf) contre 5 refus.



finally permet d'éviter au développeur d'écrire un code de nettoyage lorsqu'une exception non manipulable se produit, comme illustré dans le code suivant :

Code :
1
2
3
4
5
6
7
8
9
$db = mysqli_connect(); 
try {
   call_some_function($db);
} catch (Exception $e) {
   mysqli_close($db); 
   throw $e;
}
mysqli_close($db);
L'introduction de finally fournit au développeur une manière plus propre de gérer ce genre de problématiques. Le bloc finally s'exécute toujours lorsqu'on quitte le bloc try. Cela permet d'exécuter le bloc finally même si une exception inattendue se produit :

Code :
1
2
3
4
5
6
7
$db = mysqli_connect(); 
try {
   call_some_function($db); //La fonction peut produire des exceptions sur lequelles on ne peut intervenir anticiper
} finally {
   mysqli_close($db); 
}
Mais c'est aussi utile lorsque le code de nettoyage est contourné de façon accidentelle par un return, un continue ou un break, comme illustré ci-dessous :

Code :
1
2
3
4
5
6
7
8
try {
    return 2;
} finally {
    echo "this will be called\n";
}
//this will never be called
echo "you can not see me";
Ce code affichera « this will be called ». Le texte après le bloc try/finally ne sera pas affiché.

On peut envisager des scénarios plus sophistiqués, avec un cas imbriqué :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function foo ($a) {
   try {
      echo "1";
      try {
        echo "2";
        throw new Exception("ex");
      } catch (Exception $e) {
        echo "3";
      } finally {
        echo "4";
        throw new Exception("ex");
      }
   } catch (Exception $e) {
      echo "3";
   } finally {
      echo "2";
   }
   return 1;
}
var_dump(foo("para"));

Ce commit n'a pas engendré l'annonce (ou le lancement) d'une nouvelle version du langage. Les plus téméraires peuvent compiler la dernière branche du langage à partir de son code source.

Source : finally sur le wiki de PHP

Et vous ?

Que pensez-vous de l'intégration de ce mot clé en PHP ?
Comment faisiez-vous sans sa présence ?
  Discussion forum
20 commentaires
  • Guilp
    Membre éprouvé
    finally...

    (désolé. pas pu m'en empêcher )
  • Xinu2010
    Membre averti
    Envoyé par dourouc05
    D'ailleurs, un finally n'est pas toujours la meilleure chose au monde : si on met un return dans les blocs try ou catch, le contenu du finally sera exécuté avant le retour de fonction, c'est-à-dire qu'on ne peut plus suivre simplement le fil d'exécution du code (ça vous rappelle GOTO ?).
    Ouais enfin c'est mettre un return dans un catch qui est sale, pas le finally lui même
  • ternel
    Expert éminent sénior
    Envoyé par Lupus Michaelis
    Je n'ai jamais compris l'intérêt de finally. Comme en a parlé leternel, le RIIA est fait pour ça. Utiliser les exception sans RIIA, c'est un peu un non-sens.

    Ceci dit, PHP est un langage sale, à rustine. Et plutôt que d'avoir une gestion du scope de variables cohérent, un emplâtre finally est rajouté...
    Il y a des langages, comme le java, où le destructeur est appelé "plus tard", et oui il n'est pas vraiment possible de le définir.
    Du coup, le RIIA y est totalement irréalisable.
    Bien plus que l'absence d'héritage multiple, c'est ca qui m'énerve le plus en Java...
  • ternel
    Expert éminent sénior
    En C++ on fait du RIIA, c'est à dire une classe encapsulant la ressource.

    Le finally est implicite: destruction de toute les variables locales.

    L'équivalent c++ de :
    Code :
    1
    2
    3
    4
    5
    6
    cx = createConnection(...)
    try{
        useConnection();
    } finally {
        killConnection()
    }
    est:
    Code :
    1
    2
    3
    4
    {
    Connection cx(...);
    cx.use();
    }
    Parce que le destructeur de cx sera appelé à la sortie du bloc d'accolade.
  • arkadih
    Nouveau membre du Club
    je trouve aussi que c'est une bonne chose, que les développeurs de différents langages retrouvent leurs habitudes, le souci restant que les fonctions natives de php ne jettent pas nécessairement d'exception lors de problèmes rencontrés (certaines jouent sur la valeur de retour, certaines jettent l'exception).
    tant que ce souci ne sera pas résolu, php sera toujours en retard au niveau des exceptions de mon point de vue.
  • gl
    Rédacteur
    Envoyé par transgohan
    L'erreur est innacceptable => return avec un code d'erreur
    Si tu ne sais pas quoi faire de l'exception à cet endroit et que tu cherches juste à la faire remonter dans les couches supérieures, pourquoi la catcher et la convertir en code de retour [1] ? Pourquoi ne pas laisser le mécanisme d'exception propager l'erreur jusqu'à une couche qui est capable d'en faire quelque-chose ? c'est bien là le rôle des exceptions.

    [1] si on laisse de côté la cas particulier du code à la frontière entre un module avec exception et un qui ne les gère pas et le code historique bien entendu.
  • Paul TOTH
    Expert éminent sénior
    c'est pas mal...mais c'est pas prêt d'arriver sur l'ensemble des hébergeurs et clients
  • Gugelhupf
    Modérateur
    Que pensez-vous de l'intégration de ce mot clé en PHP ?
    Je pense que c'est une bonne nouvelle, les développeurs PHP (ou autres ) reprochaient souvent le manque du mot-clé finally.

    Comment faisiez-vous sans sa présence ?
    "Comme tout le monde ?" J'ai envie de dire... en se débrouillant.
    Pour ma part je n'ai pas eu beaucoup l'occasion de rencontrer les problèmes cités en PHP.
    En même temps, comment font ceux qui font du C++ et qui n'ont toujours pas le bloc finally ?
  • iubito
    Membre éclairé
    C'est une belle avancée, mais bien d'accord avec arkadih

    J'ai pas souvenir d'avoir utilisé des exceptions en PHP, faut dire que ça fait un bail que je n'en ai pas fait à un gros niveau.

    En java je ne peux me passer du finally, mais toutes les fonctions jettent des exceptions (erreur de syntaxe sql, erreur de connexion à la BDD...), en PHP il faudra tester les valeurs de retour et déclencher soi-même l'exception.
  • Xinu2010
    Membre averti
    Envoyé par iubito
    En java je ne peux me passer du finally, mais toutes les fonctions jettent des exceptions (erreur de syntaxe sql, erreur de connexion à la BDD...), en PHP il faudra tester les valeurs de retour et déclencher soi-même l'exception.
    Il y a des exceptions généré directement par les méthodes de l'API, comme PDOException pour les erreur sql, mais ouais c'est un peu brouillon et pas forcément uniforme.