Exceptions et PHP5

Date de publication : 13/09/2006 , Date de mise à jour : 24/01/2007


IV. Amélioration du système d'exception
IV-A. Capture automatique des exceptions
IV-B. Bascule erreur->exception


IV. Amélioration du système d'exception


IV-A. Capture automatique des exceptions

La présence de la gestion des exceptions dans certaines extensions de PHP, généralement non utilisée car non connue des développeurs, ainsi que les possibles risques d'avoir un throw égaré dans les profondeurs d'une classe impliquent que certaines exceptions soulevées peuvent ne pas être attrapées. Nous obtenons alors un message peu agréable de la sorte :

Fatal error: Uncaught exception 'Exception' with message 'Message non capturé' 
in C:\wamp\www\exception\index.php:4 
Stack trace: #0 C:\wamp\www\exception\index.php(7): showUncaughtException() #1 {main} 
thrown in C:\wamp\www\exception\index.php on line 4
Dans le cas de PDO par exemple, une exception non gérée affiche toute la chaîne de connexion incluant les données de connexion à la base de données.

Exception de connexion à la BDD avec PDO a écrit :
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42000] [1049] 
Unknown database 'jeu_de_role'' in 
c:\program files\apache group\www\dvp\tests\pdo.php:22 
Stack trace: #0 c:\program files\apache group\www\dvp\tests\pdo.php(22): 
PDO->__construct('mysql:host=loca...', 'root', '1234', Array) #1 {main} 
thrown in c:\program files\apache group\www\dvp\tests\pdo.php on line 22
Pour remédier à ce problème évident, PHP définit la fonction set_exception_handler permettant de définir une fonction de callback appelée à chaque exception soulevée et non capturée
Exemple d'utilisation de la fonction set_exception_handler

function exception_handler($myException)
{
    echo 'Exception non capturée : '.$myException->getMessage();
}

set_exception_handler('exception_handler');

throw new Exception('voici une exception');
// Affichera l'exception non capturé : voici une exception

IV-B. Bascule erreur->exception

Comme nous l'avons vu précédemment, PHP5 n'utilise pas les exceptions, il se contente de les proposer au développeur. Parallèlement, PHP permet de redéfinir le support des erreurs système. Merveilleux, nous avons tout pour faire notre propre gestion des erreurs en utilisant les exceptions.
Exemple de redéfintion de la gestion d'erreur

function exception_handler($code, $msg, $file, $line)
{
    throw new Exception($msg, $code);
}

set_error_handler('exception_handler');

try
{
    fopen();
}
catch (Exception $myException)
{
    echo '<div style="color:red">'.$myException->getMessage().'</div>';
}
Cet exemple est trop simple pour être utilisable tel quel. Il retire beaucoup d'informations par rapport à ce qu'apporterait une erreur. Pour l'étendre, nous pouvons d'une part créer une classe fille MyPHPException, chargée de ne traiter que ce type d'erreur et nous laissant libre d'étendre nos exceptions ailleurs, d'autre part, nous pouvons ajouter les informations de l'erreur dans l'exception. Par exemple, nous pouvons obtenir la ligne et le fichier dans lequel s'est produite l'erreur, ainsi que le contexte à ce stade du script. Nous pouvons ajouter aussi des informations apportées par l'exception. En effet, nous avons aussi accès au contexte lors de la levée d'exception. Ainsi, nous pouvons connaître la dernière fonction appelée, dans laquelle s'est déroulée l'erreur. Nous avons aussi accès aux tableau super globaux et aux variables locales.

Voici notre nouveau script amélioré :
Gestion complète des erreurs par les exceptions

/**
* @desc Notre classe d'exception pour les erreurs PHP
*/
class MyPHPException extends Exception
{
    /**
    * @desc Constructeur
    */
    public function __construct($msg, $code, $file, $line, $context)
    {
        $this->message = $msg;
        $this->code = $code;
        $this->line = $line;
        $this->file = $file;
        $this->context = $context;
        
        parent::__construct($msg, $code);
    }
    
    /**
    * @desc Affichage de l'erreur
    */
    public function showError()
    {
        echo 'PHP a généré l\'erreur système suivante : ['.$this->code.' | '.
            $this->getMessage().'] à la ligne '.
            $this->line.' du fichier '.$this->file;
        
        // $Mytrace contient le contexte de l'exception
        // $this->context contient le contexte de l'erreur
        
        $Mytrace = $this->getTrace();
        //print_r($Mytrace);
        if ( ! empty($Mytrace['1']['function'] ))
        {
            echo ' sur la fonction '.$Mytrace['1']['function'];
        }     
        echo '<br /><br/>Contexte lors de l\'erreur :<br/><pre>';
        print_r($this->context);
        echo '</pre>';
    }
}

/**
* @desc la fonction de callback, chargée de lancer l'exception
*/
function errorToException($code, $msg, $file, $line, $context)
{
    throw new MyPHPException($msg, $code, $file, $line, $context);
}

// redéfinition de la gestion d'erreur
set_error_handler('errorToException');

// Enfin, notre script
try
{
    fopen();
}
catch (MyPHPException $myPHPException)
{
    echo '<div style="color:red">'.$myPHPException->showError().'</div>';
}
Ceci nous affichera à l'écran :

PHP a généré l'erreur système suivante : [2 | fopen() expects at least 2 parameters, 0 given] 
à la ligne 44 du fichier .C:\wamp\www\exceptions\index.php sur la fonction fopen

Contexte lors de l'erreur :

Array
(
    [GLOBALS] => Array
 *RECURSION*
    [_ENV] => Array
        (
            [ALLUSERSPROFILE] => C:\Documents and Settings\All Users
            [CommonProgramFiles] => C:\Program Files\Fichiers communs
            [ComSpec] => C:\WINDOWS\system32\cmd.exe
            [FP_NO_HOST_CHECK] => NO
            [NUMBER_OF_PROCESSORS] => 1
            [OS] => Windows_NT
            ....
            ...
 

Valid XHTML 1.1!Valid CSS!

Copyright © 13/09/2006 Guillaume Affringue. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages et intérêts. Cette page est déposée à la SACD.

Vos questions techniques : forum d'entraide PHP - Publiez vos articles, tutoriels et cours
et rejoignez-nous dans l'équipe de rédaction du club d'entraide des développeurs francophones
Nous contacter - Hébergement - Participez - Copyright © 2000-2010 www.developpez.com - Legal informations.