IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PHP & Base de données Discussion :

Gestion d'erreurs


Sujet :

PHP & Base de données

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de nicolas66
    Profil pro
    Étudiant
    Inscrit en
    Février 2004
    Messages
    326
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2004
    Messages : 326
    Par défaut Gestion d'erreurs
    Bonsoir,

    Je suis en train de construire mon site en PHP et je me demande quelle serait la meilleure méthode pour la gestion des erreurs. Pour l'instant, j'ai par exemple une classe `sgbd` et une classe `MySQL` qui hérite de la précédente. Si je ne peux pas me connecter à une base de données, je crée un message d'erreur interne à la classe. Si l'utilisateur souhaite afficher les messages d'erreurs, il appelle une méthode qui lui donne la nature de l'erreur. En clair, ca donne ca :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    <?php
    $bd = new MySQL(serveur, login, pass, base);
     
    if( !$bd->Connect() )
            echo $bd->GetError();
     
    $bd->Deconnect();
    ?>
    Naturellement, cette méthode fonctionne mais serait-il plus judicieux d'utiliser les exceptions ou autre chose ? Merci d'avance .


    Nico.

  2. #2
    Rédacteur

    Avatar de Yogui
    Homme Profil pro
    Directeur technique
    Inscrit en
    Février 2004
    Messages
    13 721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Février 2004
    Messages : 13 721
    Par défaut
    Salut

    J'avais lu un artice à ce sujet il y a quelque temps :
    http://frederic.bouchery.free.fr/?2004/07/16/6-Comment-Simplifier-Le-Traitement-Des-Erreurs

  3. #3
    Membre chevronné Avatar de XtofRoland
    Profil pro
    Inscrit en
    Août 2005
    Messages
    357
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Août 2005
    Messages : 357
    Par défaut
    une "bonne" methode est de faire une classe pour ta connection et tu lui laisse gerer l'erreur.

  4. #4
    Membre éclairé Avatar de nicolas66
    Profil pro
    Étudiant
    Inscrit en
    Février 2004
    Messages
    326
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2004
    Messages : 326
    Par défaut
    Pourrais-tu donner un exemple simple pour préciser un peu ta pensée ? Merci .

  5. #5
    Membre Expert
    Inscrit en
    Juillet 2004
    Messages
    1 027
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 1 027
    Par défaut
    Je ne connait pas la meilleure méthode car j'ai pas du tout de recul la dessus en PHP5, ni d'ailleurs dans aucun langage possédant un système d'exception.

    M'enfin, ta classe Mysql pourrait posséder son propre jeu d'exception avec un système à code (c'est assez courant, et assez pratique pour savoir à quelle erreur on à faire programatiquement parlant), ou tout autre système qui puisse donner une explication et une identification de l'erreur correcte.
    Ce jeu d'exception pourrait être composé d'une ou plusieurs exceptions.

    Sa donnerait ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    class MysqlConnectionError extends Exception
    {
        private $test;
        public function __construct()
        {}
    }
    class MysqlQueryError extends Exception
    {
        private $test;
        public function __construct()
        {}
    }
    try
    {
        throw new MysqlQueryError();
    }catch(MysqlConnectionError $Ex)
    {
        echo "MysqlConnectionError throwed";
    }
    catch(MysqlQueryError $Ex)
    {
        echo "MysqlQueryError throwed";
    }
    Ceci dit, on peut surement faire mieux. En y adjoignant une classe qui soit capable de prendre en charge une exception. J'entends par la, sauvegarder le bug, le faire taire proprement, rediriger l'utilisateur vers une page propre, et prévenir une personne physique qu'un bug c'est produit.

    Sa pourrait donner quelque chose comme cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    class MysqlConnectionError extends Exception
    {
        private $test;
        public function __construct()
        {}
    }
    class MysqlQueryError extends Exception
    {
        private $test;
        public function __construct()
        {}
    }
    class PageException
    {
        private $pEx;
     
        public function __construct()
        {
        }
     
        public function Redirect(Exception $Ex)
        {
            $this->pEx = $Ex;
            // Ici on fait ce que l'on veut avec l'erreur du moment
            // qu'elle est proprement gérée
            var_dump($this->pEx);
        }
    }
     
    $p = new PageException();
    try
    {
        throw new MysqlQueryError();
    }catch(MysqlConnectionError $Ex)
    {
        echo "MysqlConnectionError throwed";
        $p->Redirect($Ex);
    }
    catch(MysqlQueryError $Ex)
    {
        echo "MysqlQueryError throwed";
        $p->Redirect($Ex);
    }
    J'y voit deja un problème, si on fait à une excpetion en pleine page, aux oubliettes la redirection avec le header. Il faudrait ajouter des fonctions tels que ob_start et ob_end flush ect, pour gérer l'envoie au navigateur de manière plus fine.

    Bref, c'est une idée qui me trotte dans la tête depuis un moment, mais je ne sais pas ce que cela peut valoir à l'usage.
    Car c'est plus contraignant à écrire, pour une action il faut penser à prendre en charge l'exception ect.


    Y'aurait il des personnes dans l'assemblée qui aurait déja eu à ce confronter à ces problèmes ?
    Et qui pourrait éclaircir un peut cette question.

    La solution de kikris est très plaisante, et pourrait même être amélioré 8)

    bye

  6. #6
    Rédacteur

    Avatar de Yogui
    Homme Profil pro
    Directeur technique
    Inscrit en
    Février 2004
    Messages
    13 721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Février 2004
    Messages : 13 721
    Par défaut
    De mon point de vue, la gestion automatique par la classe est discutable car cela ne te permet pas d'utiliser les constantes spéciales comme __FILE__ et __LINE__, à moins de les donner en paramètre à Connect(), ce qui serait probablement une erreur sémantique. J'aime bien utiliser ces constantes pour gérer les erreurs, ça a un petit aspect pratique que je trouve bigrement utile.

    Cela dit, j'imagine que c'est le même problème avec le lien que j'ai donné plus haut...

  7. #7
    Membre éclairé
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    882
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 882
    Par défaut
    car cela ne te permet pas d'utiliser les constantes spéciales comme __FILE__ et __LINE__
    pour ca tu les methodes getLine() et getCode()

    sinon je ne comprend pas le probleme d'epox, du moins si l'on separe le code de l'affichage

  8. #8
    Membre Expert
    Inscrit en
    Juillet 2004
    Messages
    1 027
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 1 027
    Par défaut
    sinon je ne comprend pas le probleme d'epox, du moins si l'on separe le code de l'affichage
    en l'occurence c'est une vrai/faux problème, mais une gestion plus fine de l'envoie au navigateur donne un peu plus de liberté, et ne se pose pas la question de savoir comment tu codes (séparée ou pas).
    Sa résisterai à toutes les erreurs sauf les parse bien sur...

    Par contre j'ai encore des interrogations quand à la viabilitée d'un tel système :/

    en faits je me demande comment sont gérées les erreur dans d'autres langages tels que c le cpp ou c# lorsqu'il faut mettre en place des solutions transversale.

  9. #9
    Membre éclairé
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    882
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 882
    Par défaut
    moi perso j'utilise MVC et je recupere toute les execptions dans le controlleur
    et je lance une methode displayexecption apres les avoir enregistés

  10. #10
    Membre éclairé Avatar de nicolas66
    Profil pro
    Étudiant
    Inscrit en
    Février 2004
    Messages
    326
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2004
    Messages : 326
    Par défaut
    A ce sujet, j'ai trouvé un article intéressant sur le sujet : http://classes.scriptsphp.net:81/art...les-exceptions.

    Comme le signale ePoX, il faudrait prendre en compte le cas du header à l'aide des fonctions qu'il a cité . Je vais essayer de continuer à creuser ça ces jours-ci.

    Finalement, je ne pense pas que ma question soit si futile que ça car je pense que beaucoup de personnes ont dû se poser la question lorsqu'un projet commence à prendre de l'ampleur .

  11. #11
    Membre Expert
    Inscrit en
    Juillet 2004
    Messages
    1 027
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 1 027
    Par défaut
    Tant mieux pour toi jeff_!, mais si tout le monde suivait le même modèle sa se saurait, et ce n'est pas le cas.

    Donc, ce vrai/faux problème peut être résolu, sa ne lui ferait pas de mal.

    Ceci dit c'est du détail. Et ce n'est pas vraiment ce qui m'interessait la dedans, mais plutot de savoir si dans d'autres langages/projets les méthodes utilisées pour gérer les erreurs d'execution ressemblait grosso modo à ce que j'ai proposées ou si il existait d'autres voies encore plus interessante ou que sais je encore.

    Edit :
    Cet article est super interessant

  12. #12
    Rédacteur

    Avatar de Yogui
    Homme Profil pro
    Directeur technique
    Inscrit en
    Février 2004
    Messages
    13 721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yonne (Bourgogne)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Février 2004
    Messages : 13 721
    Par défaut
    J'imagine qu'il doit y avoir moyen de combiner la technique expliquée par Frédéric Bouchery et la classe Exception (quoique cela aurait peu d'intérêt) mais, perso, je trouverais ça plus lourd d'utiliser la classe Exception que de faire un simple or die(), sans parler de la technique de F.B.

    Sérieusement, je me vois mal faire un try{} puis un catch(){} à chaque requête alors que je pourrais ne rien mettre du tout...
    Bien sûr, si la classe est bien faite, je n'aurai pas souvent à faire mon try et mon catch mais voilà, je viens de mettre le doigt sur le centre du problème, il faut bien prévoir sa classe. Ce qui me fait peur, c'est plutôt d'avoir du code tellement éparpillé que je ne saurai plus où donner de la tête alors que tout pourrait être réglé en 4 lignes en début de script.

  13. #13
    Membre Expert
    Inscrit en
    Juillet 2004
    Messages
    1 027
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 1 027
    Par défaut
    Je relance le sujet parceque j'ai trouvé un truc sympa.

    Il y' à une fonction set_exception_handler en PHP5 qui sert justement à rattrapé les exception dans le gestionnaire que l'on veut.

    Donc j'ai fait sa :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
     
    <?php
    class Page 
    {
    	private static $pInstance = NULL;
     
    	private $pExceptionHandler;
    	private $pErrorHandler;
    	private $pTraceErrorHandler;
     
    	private $pRecordedErrors;
     
    	private function __construct()
    	{
    		/* */
    		date_default_timezone_set(date_default_timezone_get());
     
    		/* */
    		$this->pExceptionHandler = set_exception_handler(array($this , "OnException"));
    		$this->pErrorHandler = set_error_handler(array($this , "OnError"));
    		$this->pTraceErrorHandler = array(&$this , "TraceErrors");
    		$this->pRecordedErrors = new ErrorList();
    		ob_start();
    	}
     
    	public function OnException( $Ex )
    	{
    		$this->pRecordedErrors->add( $Ex );
    	}
     
    	public function OnError( $errno, $errstr, $errfile, $errline )
    	{
    		$Ex = new PageError( $errstr, $errno, $errfile, $errline );
    		$this->pRecordedErrors->add( $Ex );
    	}
     
    	public function __get( $prop )
    	{
    	   switch( $prop)
    	   {
    		   case "Exception_handler":
    			   return $this->pExceptionHandler;
    		   break;
    		   case "Error_handler":
    			   return $this->pErrorHandler;
    		   break;
    		   case "Trace_error_handler":
    			   return $this->pTraceErrorHandler;
    		   break;
    	   }
    	}
     
    	public function __set( $prop , $value )
    	{
    	   switch( $prop)
    	   {
    		   case "Exception_handler":
    			   $this->pExceptionHandler = set_exception_handler($value);
    		   break;
    		   case "Error_handler":
    			   $this->pErrorHandler = set_error_handler($value);
    		   break;
    		   case "Trace_error_handler":
    			   $this->pTraceErrorHandler = $value;
    		   break;
    	   }
    	}
     
    	private function TraceErrors()
    	{
    	   echo "Erreur d'execution :";
    	   echo "<br/>";
    	   echo "<br/>";
    	   for($i=0,$ii=count( $this->pRecordedErrors );$i<$ii;$i++)
    	   {
    		   if( is_object ($this->pRecordedErrors[$i]) )
    		   {
    				echo "Message : ".$this->pRecordedErrors[$i]->getMessage()."<br>";              // message de l'exception
    				echo "Code : ".$this->pRecordedErrors[$i]->getCode()."<br>";                // code de l'exception
    				echo "File : ".$this->pRecordedErrors[$i]->getFile()."<br>";                // nom du fichier source
    				echo "Line : ".$this->pRecordedErrors[$i]->getLine()."<br>";                // ligne du fichier source
    				echo "Trace As String : ".$this->pRecordedErrors[$i]->getTraceAsString()."<br>";        // chaîne formattée de trace
    				foreach( $this->pRecordedErrors[$i]->getTrace() as $Key => $Value)
    				{
    					if( is_array($Value) )
    					{
    						foreach($Value as $_Key => $_Value)
    						{
    							echo $_Key. " : ".$_Value."<br>";
    						}
    					}
    					else
    					{
    						echo $Key. " : ".$Value."<br>";
    					}
    				}
    				echo "<br/>";
    				echo "<br/>";
    		   }
    	   }
    	}
     
    	public static function getInstance()
    	{
    		if( self::$pInstance == NULL ) self::$pInstance = new Page();
     
    		return self::$pInstance;
    	}
     
    	public function __destruct()
    	{
    		if( count( $this->pRecordedErrors ) > 0)
    		{
    			while( ob_get_level () > 0 )
    			{
    				ob_end_clean();
    			}
    			call_user_func($this->pTraceErrorHandler , $this->pRecordedErrors);
    		} 
    	}
    }
    class PageError extends Exception
    {
    	public function __construct($message , $code , $file , $line )
    	{
    		parent::__construct($message, $code);
    		$this->file = $file;
    		$this->line = $line;
    	}
    }
    class ErrorList extends ArrayObject
    {
    	public function __construct()
    	{
    		parent::__construct();
    	}
     
    	public function add( Exception $Ex )
    	{
    		parent::append ( $Ex );
    	}
    }
    $P = Page::getInstance();
    echo "Je ne serais pas affiché !";
    $a = 2/0;
    echo "Je ne serais pas affiché !";
    throw new Exception("yopyop");
    /*
    Affiche 
    
    Erreur d'execution :
    
    Message : Division by zero
    Code : 2
    File : D:\www\blog\class\libs\class.page.php
    Line : 144
    Trace As String : #0 D:\www\blog\class\libs\class.page.php(144): Page->OnError(2, 'Division by zer...', 'D:\www\blog\cla...', 144, Array) #1 {main}
    file : D:\www\blog\class\libs\class.page.php
    line : 144
    function : OnError
    class : Page
    type : ->
    args : Array
    
    
    Message : yopyop
    Code : 0
    File : D:\www\blog\class\libs\class.page.php
    Line : 146
    Trace As String : #0 {main}
    
    */
    ?>
    De cette manière il n'y à plus reellement besoin de ce prendre la tête pour la moindre requete.

    La classe enregistre les erreurs (warning et exception non gérée) au fur et à mesure. Lorsque vient le moment de l'appel à __destruct (automatique à la fin du script) elle dépile les ob_start créé (il peut y'en avoir plusieurs) et les vide.
    Ensuite elle affiche les différents messages d'erreur dans leur ordre d'apparition, si besoin est.
    Le gestionnaire qui affiche les erreurs, est une gestionnaire par défaut.

    Après il est possible de gérer soit même les différents gestionnaire avec les setter.

    Avez vous quelques remarques ou suggestions ?

    bye

Discussions similaires

  1. gestion d'erreur et de transactions....
    Par Dge dans le forum MS SQL Server
    Réponses: 9
    Dernier message: 08/02/2006, 22h20
  2. [Struts-Validator] Gestion d'erreurs
    Par sylvain_neus dans le forum Struts 1
    Réponses: 14
    Dernier message: 09/04/2004, 15h15
  3. [XSLT]Est ce qu'il y'a la gestion des erreur en xslt ?
    Par miloud dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 04/02/2004, 17h19
  4. [LG]tests pour la gestion d'erreur
    Par le 27 dans le forum Langage
    Réponses: 3
    Dernier message: 22/12/2003, 20h44
  5. [LG]gestion des erreurs
    Par frontin dans le forum Langage
    Réponses: 3
    Dernier message: 29/11/2003, 22h41

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo