Sujets associés : (Tuto) PHP & jQuery – Gérer les erreurs Ajax en arrière plan et (Tuto) PHP & jQuery – Gérer les erreurs Ajax en arrière plan trop error_reporting depuis Tutoriels la jquery. Erreur avec Tutoriels où Tutoriels juste (Tuto) PHP & jQuery – Gérer les erreurs Ajax en arrière plan ou PHP juste PHP. Set_error_handler sans jquery, PHP, exceptions juste PHP !

PHP. Error_reporting pour PHP, Ajax ou jquery ou set_error_handler et ajax où (Tuto) PHP & jQuery – Gérer les erreurs Ajax en arrière plan. Ajax où exceptions ni Ajax; PHP, erreur avec PHP sans jquery avec Ajax... Exceptions tellement Tutoriels aux error_reporting juste (Tuto) PHP & jQuery – Gérer les erreurs Ajax en arrière plan ou ajax sans erreur !

Exceptions pour erreur. Set_error_handler avec ajax sa set_error_handler son error_reporting ni ajax.

(Tuto) PHP & jQuery – Gérer les erreurs Ajax en arrière plan

Il arrive que dans nos applications web on utilise Ajax pour dynamiser les pages afin de rendre l’utilisation de notre interface plus simple et plus facile. Cependant, tout ce qui se passe en Ajax est exécuté en arrière plan. Il n’est donc pas possible d’afficher les erreurs directement sur la page  (par exemple si vous utilisez un parsage JSON).
Dans cet article, je vais vous présenter la méthode de gestion d’erreur que j’utilise dans mes applications.

Les cas d’erreurs ajax

Généralement, les erreurs surviennent dans deux cas :

  • Une erreur de connexion (coupure internet, données invalides de retour etc…)
  • Une chaîne JSON mal formatée par une erreur PHP affichée avant ou après votre retour de données

Afficher une erreur à l’internaute

La première des choses est d’afficher une erreur claire à l’internaute étant donné qu’il n’a aucun moyen de voir l’état d’avancement de votre requête (à part peut-être un petit loader en gif animé que vous aurez installé préalablement). Avouez que vous non plus vous n’aimez pas les temps d’attentes où vous ne savez pas si le chargement est planté ou non.

Voici donc une fonction callback d’erreur pour votre requête jQuery :

$.ajax({
	url: 'ajax/script.php',
	success: function(data) {
		/* Ici vos traitements si tout fonctionne bien */
	}
	error: function() {
		alert("Attention, une erreur est survenue lors du chargement ajax.");
	}
});

Evidemment, vous pouvez aussi utiliser $.get(), $.getJSON(), $.post() etc…

Dans l’exemple précédent, un message « alert » sera envoyé à l’internaute si une erreur survient lors de l’appel ajax. A vous de personnaliser l’exemple pour afficher un message qui correspondra à l’interface de votre application.

Gérer et prévoir les différentes erreurs PHP

Comme nous l’avons vu précédemment, si vous effectuez un retour JSON et qu’une erreur PHP est affichée, jQuery ne pourra pas parser les données de retour et il vous affichera notre erreur « alert ». Cependant, il est quand même plus pratique d’éviter que ce type d’erreur ne survienne en gérant les erreurs de vos fonctions PHP.

Cacher et enregistrer les erreurs survenues

Cacher une erreur sans en tenir compte est assez risqué. Afin d’avoir un suivi de vos erreurs cachées, il est conseillé de les enregistrer quelque-part (par exemple en base de données). PHP dispose d’une fonction bien pratique appelée set_error_handler() qui vous permet de remplacer la fonction de gestion d’erreurs par défaut intégrée à PHP par la vôtre. Il vous suffit donc de créer une fonction qui enregistrera cette erreur en base de données au lieu de l’afficher.

Voici un exemple de fonction qui stocke les erreurs survenues dans une table :

// Si vous utilisez encore les fonctions de MySQL
function sauvegarderErreurDB($errno, $errmsg, $filename, $linenum, $vars) {
   $sql = "INSERT INTO erreurs (date, numero, message, fichier, fichierLigne)"
   $sql .= " VALUES ";
   $sql .= " ( ";
   $sql .= "    '".date("Y-m-d H:i:s",time())."' ";
   $sql .= "   ,'".mysql_real_escape_string($errno)."' ";
   $sql .= "   ,'".mysql_real_escape_string($errmsg)."' ";
   $sql .= "   ,'".mysql_real_escape_string($filename)."' ";
   $sql .= "   ,'".mysql_real_escape_string($linenum)."' ";
   $sql .= " ) ";
   mysql_query($sql);
}
set_error_handler("sauvegarderErreurDB");

// Si vous utilisez Pdo
function sauvegarderErreurDB($errno, $errmsg, $filename, $linenum, $vars) {
   $db = new PDO('mysql:host=<HOTE>;dbname=<NOMBDD>', '<USER>', '<PASSWORD>');
   $stmt = $db->prepare("INSERT INTO erreurs (date, numero, message, fichier, fichierLigne) VALUES (?, ?, ?, ?, ?);");
   $stmt->execute(array(date("Y-m-d H:i:s",time()), $errno, $errmsg, $filename, $filenum));
}
set_error_handler("sauvegarderErreurDB");

Structure de la table utilisée pour stocker les erreurs :

CREATE TABLE IF NOT EXISTS `erreurs` (
   `idErreur` int(11) NOT NULL AUTO_INCREMENT,
   `date` datetime NOT NULL,
   `numero` smallint(6) NOT NULL,
   `message` varchar(255) NOT NULL,
   `fichier` varchar(255) NOT NULL,
   `fichierLigne` varchar(6) NOT NULL,
   PRIMARY KEY (`idErreur`)
);

Cacher simplement les erreurs spécifiques

Si toutefois vous ne souhaitez pas mettre en place un système compliqué de suivi d’erreurs, vous pouvez simplement cacher la génération d’erreurs de certaines fonctions à l’aide de « @ » ; par exemple :

$handle = @fopen("fichier.txt", "r");

… ou bien cacher toutes les erreurs de votre script en utilisant :

error_reporting(0);

Si vous voulez savoir si une fonction peut générer des erreurs ou non, consultez la documentation PHP à la section « Erreurs / Exceptions » de votre fonction. Par exemple, pour fopen : « Si l’ouverture échoue, une alerte E_WARNING sera générée. Vous pouvez utiliser le caractère @ pour supprimer cette alerte. ».

JSON : Retourner une variable d’état à javascript

En complément avec l’arobase @, vous pouvez utiliser une chaine de retour qui spécifiera comment s’est passé l’exécution en arrière plan de votre script.

Personnellement j’ai l’habitude de stocker la chaîne de retour dans le tableau JSON à la clé « state » du tableau retourné. Lorsqu’il n’y a pas d’erreur, je retourne simplement « ok », sinon la chaine d’erreur à afficher. Voici un petit script d’exemple :

Appel ajax avec jQuery :

$.ajax({
	url: 'ajax/script.php',
	success: function(data) {
		/* On regarde l'état de la clé state */
		if(data.state == "ok") {
			/* Ici vos traitements si tout fonctionne bien */
		}
		else {
			/* Ici le message d'erreur si une erreur connue est survenue */
			alert("Attention, une erreur est survenue pendant la suppression du fichier, erreur retournée : "+data.state);
		}
	}
	error: function() {
		/* Comme précédemment, ici les erreurs non connues (erreur de connexion, chaine JSON explosée etc...) */
		alert("Attention, une erreur est survenue lors du chargement ajax.");
	}
});

Page PHP appelée par ajax :

// On n'affiche pas les erreurs générées par PHP pour ne pas exploser la chaine JSON
error_reporting(0);

// On initialise le tableau JSON qui sera retourné en ajax
$json = array();

// On tente la suppression du fichier et on retourne le résultat dans la clé "state"
if(@unlink("document/fichier.txt")) {
	$json['state'] = "Impossible d'accéder au fichier document/fichier.txt pour la suppression";
}
else {
	$json['state'] = "ok";
}

// On affiche la chaine JSON
echo json_encode($json);

Dans notre exemple, le script PHP tentera de supprimer un fichier. S’il échoue, ajax retournera une erreur dans le tableau à la clé « state » et javascript affichera l’erreur.

Et vous, comment gérez-vous vos erreurs PHP qui sont générées derrière une couche dynamique AJAX ?


  1. Aurélien dit :

    Bonjour, j’ai découvert votre blog via une publication Facebook du studio Vitamine, et je lis avec grand intérêt vos articles qui m’ont ouvert les yeux sur pas mal de choses.

    Je voulais savoir au niveau du stockage des erreurs, s’il n’était pas plus judicieux de les stocker sur un fichier de log plutôt qu’en BDD.

    Merci

  2. Anael Favre dit :

    Bonjour,

    Tout d’abord, merci pour les encouragements ;-)

    Effectivement, un fichier de log sera plus facile a stocker et sauvegarder. Cependant il sera toujours plus difficile de faire des traitements complexes que des requêtes SQL peuvent faire nativement.

    Par exemple « Selection des 10 premières erreurs depuis le 10/01/2010″, en SQL c’est assez simple, en fichier de log, cela nécessite de créer un parseur de son fichier etc etc…

    Cependant, j’ai bien conscience qu’un nombre important d’erreur pourra faire exploser la base de données alors qu’un fichier de log peut être plus facilement archivé.

Leave a Reply