JeuWeb - Crée ton jeu par navigateur
[ Réglé ] De la gestion des erreurs - Version imprimable

+- JeuWeb - Crée ton jeu par navigateur (https://jeuweb.org)
+-- Forum : Discussions, Aide, Ressources... (https://jeuweb.org/forumdisplay.php?fid=38)
+--- Forum : Programmation, infrastructure (https://jeuweb.org/forumdisplay.php?fid=51)
+--- Sujet : [ Réglé ] De la gestion des erreurs (/showthread.php?tid=2139)

Pages : 1 2


[ Réglé ] De la gestion des erreurs - Plume - 13-12-2007

Bonjour !

J'aurais souhaité votre avis sur la gestion des erreurs ainsi qu'une participation active.

Comme je n'ai pas l'intention de réinventer la roue, pourriez vous me dire s'il est utile d'utiliser une classe pour gérer les erreurs - système & autres. Auriez vous également des sources qui soient simples, comprendre qui ne présentent rien de superficiel, où on ne trouve que le strict nécessaire. Si jamais les besoins évoluent, je saurais me débrouiller Smile

Merci,
Lex.


RE: De la gestion des erreurs - naholyr - 13-12-2007

Un début de réponse :
naholyr a écrit :Étant dans un contexte objet, tu pourras utiliser avantageusement les exceptions. Sinon tu peux également implémenter la gestion d'erreur dans la classe elle-même, ou encore utiliser les "user_error".

Exemple d'utilisation des exceptions :
Code PHP :
<?php 
// Déclaration
class Template {
...
function
__construct($template) {
if (
is_file($template)) {
$this->file = $template;
} else {
throw new
Exception('File ' . $template . ' not found');
}
...
}
...
}

// Utilisation (on intercepte "silencieusement" l'erreur)
try {
$tpl = new Template('fichier.tpl');
} catch (
Exception $e) {
die(
'Oh la la :( : ' . $e->getMessage());
}

Exemple d'implémentation de la gestion d'erreur dans la classe elle-même :
Code PHP :
<?php 
// Déclaration
class Template {
var
$error;
...
function
__construct($template) {
$this->error = null;
if (
is_file($template)) {
$this->file = $template;
} else {
$this->error = 'Error : file ' . $template . ' not found';
}
}
}

// Utilisation
$tpl = new Template('fichier.tpl');
if (
$tpl->error) {
die(
'Oh la la :( : ' . $tpl->error);
}

Je suis personnellement bien partisan des exceptions, car leur propagation permet de les gérer au niveau où on le souhaite, et de vraiment gérer finement les types d'erreurs grâce simplement aux classes des exceptions :
Code PHP :
<?php 
// Mes propres exceptions à moi tout seul
class MyErrorException extends Exception {
}

// Un exemple d'utilisation
try {
// Un code qui peut éventuellement lever une exception
} catch (FileNotFoundException $e) {
// C'est une exception de type "FileNotFound" qui a été levée
} catch (DivisionByZeroException $e) {
// w00t, division par zéro !
} catch (MyErrorException $e) {
// C'est mon exception à moi :)
} catch (Exception $e) {
// Autre exception non traitée avant, on aurait aussi pu ne pas
// mettre ce dernier catch(), afin de dire à PHP «laisse courir les
// autres exceptions, ce sont les niveaux au-dessus qui se
// chargeront de les intercepter.
}



RE: De la gestion des erreurs - Plume - 13-12-2007

A ce sujet, j'comprend pas cette histoire de faire remonter une exception >.<

[EDIT]
Code PHP :
<?php 
throw new Exception('File ' . $template . ' not found');
Code PHP :
<?php 
catch (Exception $e)
Si j'avais fait plutôt :
Code PHP :
<?php 
catch (FileNotFoundException $e)
Dois-je quand même faire :
Code PHP :
<?php 
throw new Exception('File ' . $template . ' not found');
Ou bien il se passe quelque chose par défaut ? Un message prédéfini .. Que'que chose quoi ^^

Lex.


RE: De la gestion des erreurs - naholyr - 13-12-2007

Non, si tu veux intercepter une exception spécifique, il faut bien évidemment que ce soit cette exception spécifique qui ait été levée. En l'occurrence il faudra donc exécuter
Code PHP :
<?php 
throw new FileNotFoundException(...)
Mais il faut que ce type d'exception existe au préalable Smile
Code PHP :
<?php 
class FileNotFoundException extends Exception { }

Une astuce pour générer à la volée n'importe quel type d'exception en utilisant les autoloaders :
Code PHP :
<?php 
function __autoload($className) {
// Chargement normal des classes
...
// Création à la volée des classes d'exception (déclaration facultative)
if (substr($className, -9) == 'Exception' && !class_exists($className)) {
eval(
'class ' . $className . ' extends Exception { }');
}
}
Mais bon c'est pas forcément une super idée de rendre facultative la déclaration des classes d'exception, car on perd éventuellement l'avantage de l'autocomplétion de son éditeur favori, et surtout on n'est pas à l'abri d'une faute de frappe qui pour le coup passerait totalement inaperçu.

===> http://fr2.php.net/manual/en/language.exceptions.php


RE: De la gestion des erreurs - Zamentur - 13-12-2007

Idem j'ai jamais utilisé les exeption en php (en javascript oui). Celà dit çà à l'air d'etre pas mal

Pour le moment j'utilise set_error_handler
et donc je l'attache avec une fonction qui s'occupe de la gestion des erreurs de PHP et aussi de mes erreurs que je peux definir moi meme grace à trigger_error().

En l'occurence j'enregistre les erreurs dans une base de donnée, ce qui permet par la suite de voir la frequence d'une erreur et de corriger le probleme.


fichier error_control.php
Code PHP :
<?php
function gestion_erreur($errno, $errmsg, $filename, $linenum) {

if (
error_reporting()) {
$errortype = array(
1 => "Erreur",
2 => "Alerte",
4 => "Erreur d'analyse",
8 => "Note",
16 => "Erreur interne",
32 => "Alerte interne",
64 => "Erreur de compilation",
128 => "Alerte de compilation",
256 => "Erreur utilisateur",
512 => "Alerte utilisateur",
1024=> "Note utilisateur"
);
//Enregistrement dans la bdd OU affichage si programmeur/ betatesteur
//[...]
}
}
set_error_handler("gestion_erreur");
?>

Un debut de fichier type sans les commentaires
Code PHP :
<?php
require_once('error_control.php');
//Si j'ai besoin de faire creer une erreur
trigger_error("Impossible de diviser par zéro", E_USER_ERROR);

//Si j'ai besoin de désactiver les erreurs (donc ignorance total de ces derniere)
error_reporting(0);


Ca c'est ce que je faisais avant, je suis justement en train de voir si avec les classes (peut etre les exeption ce ne serais pas mieux!)


RE: De la gestion des erreurs - naholyr - 13-12-2007

Le gros problème de PHP c'est qu'il n'y a pas des exceptions partout. Toutes les fatal error devraient être remplacées par des exceptions si on voulait en faire un vrai langage objet. Ou au moins les erreurs dans le cadre de la POO, typiquement
Code PHP :
<?php 
$o
= new stdClass;
$o->coucou();
Citation :Fatal error: Call to undefined method stdClass::coucou() in Command line code on line 1
C'est nul... Ça devrait lever une exception, afin de rester dans un modèle objet cohérent. Dans tout vrai langage objet on a les erreurs "dures" qui relèvent de la compilation (parse error, strict warning, etc...) les erreurs "douces" (notice & warning), mais toutes les erreurs fatales au runtime sont des exceptions (surtout pour un langage interprété). Mais bon, on ne va pas refaire PHP hein Smile

De toute façon, le meilleur langage objet, c'est Python Tongue (et juste derrière, Javascript ^^)

Plus sérieusement, mon intérvention peut sembler un peu HS, mais elle est surtout là pour prévenir qu'il ne faut pas s'étonner de certaines incohérences du langage, il traine un lourd passif de langage procédure "bricolo" que les dév's n'ont pas encore été prets à abandonner.


RE: De la gestion des erreurs - Plume - 13-12-2007

Je suis déjà sur le manuel concernant les exceptions. C'est pas mal fourni. Reste plus qu'à tout assimiler :roll:

Je pensais que des types d'exception existaient originellement. C'est pas le cas ?

Y a autre chose que je cerne pas. Tu écris ça :
Code PHP :
<?php 
catch (Exception $e) {
// Autre exception non traitée avant, on aurait aussi pu ne pas
// mettre ce dernier catch(), afin de dire à PHP «laisse courir les
// autres exceptions, ce sont les niveaux au-dessus qui se
// chargeront de les intercepter.
}
Et dans le manuel, il dise que :
Citation :Lorsqu'une exception est jetée, le code suivant le traitement ne sera pas exécuté et PHP tentera de trouver le premier bloc catch correspondant. Si une exception n'est pas attrapé, une erreur fatale issue de PHP sera envoyée avec un message spécifiant que l'exception n'a pu être attrapée à moins qu'un gestionnaire ne soit défini avec la fonction set_exception_handler().

En plus, je comprends pas - selon ce que tu dis - comment, si je ne met pas le dernier catch, une exception non attrapée auparavant peut traiter une exception qui ne la concerne pas.

Lex.


RE: De la gestion des erreurs - naholyr - 13-12-2007

w00t, ça a l'air confus ^^
Dans
Code PHP :
<?php 
catch (ClassName $e) { ... }
je n'attrape l'exception que si elle est de la classe "ClassName" (ou qu'elle en hérite).
Donc si à aucun moment je n'intercepte la classe "Exception", il se peut que je laisse passer certaines exceptions. Dans ce cas, l'exécution du contexte en cours s'interrompt, et l'exception remonte au contexte appelant. Exemple :

Code PHP :
<?php 
// Mes types d'exceptions
class NotAFileException extends Exception {}
class
NotReadableException extends Exception {}

// Une fonction qui vérifie que le paramètre est un nom de fichier valide
// @throws NotAFileException
function isAFile($file) {
if (!
is_file($file)) {
throw new
NotAFileException('file not found : ' . $file);
}
}

// Une fonction qui renvoie le contenu d'un fichier, ou lève une exception
// @throws NotAFileException
// @throws NotReadableException
function readAFile($file) {
if (!
is_readable($file)) {
throw new
NotReadableException('cannot read : ' . $file);
}
isAFile($file); // Lève FileNotFoundException si ce n'est pas un fichier,
// on n'essaie pas de l'intercepter, on laisse le "contexte appelant" s'en charger
return file_get_contents($file);
}

// Une fonction qui récupère le contenu d'un fichier, chaine vide s'il ne s'agit pas d'un fichier valide
// @throws NotReadableException
function fileContent($file) {
try {
$content = readAFile($file); // Peut lever NotReadableException (problème de droit)
// ou NotAFileException (n'est pas un fichier)
} catch (NotAFileException $e) { // Il ne s'agit pas d'un fichier valide
return '';
}
// On n'intercepte pas l'exception NotReadable
}

// Dans le code principal :
try {
$content = fileContent('monFichier'); // Seule l'exception "NotReadableException" peut être levée,
// puisque fileContent intercepte et traite "NotAFileException"
} catch (NotReadableException $e) {
echo
'problème de droit';
} catch (
Exception $e) {
echo
'autre exception non traitée : ' . $e->getMessage();
}
Est-ce que le jeu de propagation des exceptions semblent un peu plus explicite comme ça ?

L'idée, c'est qu'on peut vraiment aller du plus fin au plus général, en précisant ou non le type de l'exception, et en jouant avec l'héritage :
Code PHP :
<?php 
class MathException extends Exception {}
class
DivisionByZeroException extends MathException {}
class
NumberTooBigException extends MathException {}

class
FileException extends Exception {}
class
FileNotFoundException extends FileException {}
class
FileNotWritableException extends FileException {}

// etc...
En définissant une hiérarchie des exceptions, on pourra aussi bien récupérer toute exception levée de manière générique (avec "catch (Exception $e)") qu'une exception concernant le système de fichier de manière générale (catch (FileException $e)), ou même très finement l'exception qui indique que le fichier n'a pas été trouvée (catch (FileNotFoundException $e)). Etc... Wink


RE: De la gestion des erreurs - Plume - 13-12-2007

Niquel .. Je crois Smile

Code PHP :
<?php 
// Dans le code principal :
try {
$content = fileContent('monFichier'); // Seule l'exception "NotReadableException" peut être levée,
// puisque fileContent intercepte et traite "NotAFileException"
} catch (NotReadableException $e) {
echo
'problème de droit';
} catch (
Exception $e) {
echo
'autre exception non traitée : ' . $e->getMessage();
}
Si je ne fais pas le dernier catch & que j'ai une erreur quand même, j'aurais un fatal ?


RE: De la gestion des erreurs - naholyr - 13-12-2007

Oui, car tu es dans le code principal, donc ton exception n'est vraiment jamais catchée et parvient à s'échapper "jusqu'au bout". Ce n'est pas une tout à fait une fatal error, mais en l'occurrence comme une exception interrompt la suite de l'exécution dans le contexte courant uniquement, et que le contexte courant est le contexte global lui-même (pas une fonction ou une classe), cela reviendra au même
Citation :Fatal error: Uncaught exception 'Exception' with message 'message d'erreur' in Command line code:1
Stack trace:
#0 {main}
thrown in Command line code on line 1

C'est grâce à ce système que dans un modèle MVC le code du contrôleur principal ressemble en gros à
Code PHP :
<?php 
try {
$this->execute();
} catch (
Exception $e) {
// Afficher un beau message d'erreur formaté avec la pile d'erreur et tout et tout
}
et que Symfony nous affiche des informations de débuggage très utiles en cas d'erreur Smile