PHP 7.1 : la gestion d'erreurs et ses améliorations

7 septembre 2016php, php-7.1
 Cet article a été rédigé il y a plusieurs années et peut ne plus être tout à fait à jour…

This post is also available in English.
Ceci est le troisième article d’une série à propos de PHP 7.1.


PHP 7.1 apporte plusieurs améliorations au niveau de la gestion des erreurs ou des exceptions.

Catching Multiple Exception Types

Tout d’abord, nous pouvons désormais attraper plusieurs types d’exceptions différents avec le mot-clé catch : il suffit de séparer les types d’exceptions par un |.

Par exemple, si nous avons plusieurs types d’exceptions définis de la manière suivante :

class Plop extends Exception {}
class Blah extends Exception {}
class Another extends Exception {}

Nous pouvons lever une exception d’un type ou d’un autre, comme ci-dessous. La partie intéressante est le premier bloc catch, qui va gérer de la même manière les exceptions de types Plop et Blah :

try {
    switch (mt_rand(0, 2)) {
        case 0: throw new Plop();
        case 1: throw new Blah();
        case 2: throw new Another();
    }
}
catch (Plop | Blah $e) {
    printf("1er catch : %s\n", get_class($e));
}
catch (Another $e) {
    printf("2nd catch : %s\n", get_class($e));
}

Le principe de la gestion d’exceptions ne change nullement : il s’agit ici uniquement d’un enrichissement de la syntaxe. Nous évitons ainsi le copier-coller deux fois du même bloc de gestion, lorsqu’il doit être utilisé pour deux types d’exceptions différents.

‣ La RFC : Catching Multiple Exception Types


Throw Error in Extensions

PHP 7.0 a introduit un changement important au niveau de la gestion d’erreurs : une partie des erreurs fatales levées par le moteur ont été converties en exceptions, de type Error ou d’une classe en héritant.
PHP 7.1 étend ce comportement à la majorité des erreurs fatales qui étaient auparavant levées par des extensions fournies avec PHP.

Par exemple, dé-sérializer une chaine invalide qui aurait dû correspondre à un objet DateTime ne lève plus une Fatal Error avec PHP 7.1 :

// 'timezone-type' au lieu de 'timezone_type'
$serialized = 'O:8:"DateTime":3:{s:4:"date";s:26:"2016-08-14 12:31:50.000000";s:13:"timezone-type";i:3;s:8:"timezone";s:3:"UTC";}';
$dt = unserialize($serialized);
var_dump($dt);

Cette portion de code, avec une chaine $serialized incorrecte (j’ai remplacé un _ par un -), mènera en PHP 7.1 à ceci :

Fatal error: Uncaught Error: Invalid serialization data for DateTime object in .../demo-01.php:5

J’ai ici pris une Error, que je n’ai pas attrapée et qui a donc mené à une Fatal Error.
J’aurais pu entourer tout ceci d’un bloc try/catch et éviter cette erreur fatale et gérer convenablement le cas.

‣ La RFC, qui liste l’ensemble des cas adaptés : Throw Error in Extensions