Vous êtes sur la page 1sur 5

Grer les erreurs MySQL en PHP sans or die

Utiliser or die(...) aprs une commande MySQL est devenu une mauvaise habitude pour
grer les erreurs. Cette pratique est encourage par la documentation officielle PHP, dans ses
exemples de scripts illustrant les fonctions, mais galement dans les forums o elle est
banalise jusqu' devenir un "standard" de programmation.

Ce tutoriel vous montrera les limites de cette pratique et fournira une mthodologie pour
coder propre sans pour autant alourdir les scripts.

Tutoriel par Jerome A (Ingnieur)


Cr le 17 Mars 2009, mis jour le 03 Novembre 2012 (107062 lectures)
Tags : php, bonnes pratiques, dveloppement, mysql, erreur, pdo

Sommaire

1. Know your enemy : or et die


2. Solutions
o Tests avec if/else
o Utilisation de PDO
o Classe wrapper du module mysql

Know your enemy : or et die

Avant toute chose, il est important de comprendre pourquoi or die(...) est utilis
mauvais escient. Pour ce faire, il faut se pencher sur chaque instruction : or et die.

L'oprateur or

or est l'oprateur logique "ou", dont la table est :

a b a or b
000
011
101
111
On dduit de cette table la rgle suivante : x {0,1}, 1 or x = 1.

Dans un script, les expressions d'une opration or sont values de gauche droite. Par souci
d'optimisation, et conformment la rgle prcdente, la premire expression "vraie" valide le
rsultat, les expressions suivantes n'ont plus besoin d'tre values.

La fonction die

die est un alias de exit : c'est une fonction native de PHP qui permet de stopper l'excution
du script. Si une chane de caractres est passe en argument, elle est affiche avant l'arrt. Si
un entier est pass en argument, il peut tre utilis comme statut de sortie (0 signifiant que le
programme s'est termin avec succs).

Utilisation de or die dans la gestion d'erreur

Le rgle dterminant le rsultat d'un ou logique est applique lors des connexions au serveur
MySQL. Soit la portion de code suivante :

$link = mysql_connect(...) or
die('Impossible de se connecter au serveur MySQL');

Si la connexion russit, mysql_connect retourne un identifiant de connexion. Cet identifiant


n'tant pas considr comme "faux", il est converti en boolen true qui valide le rsultat, die
n'est donc pas excute.

Si la connexion choue, mysql_connect retourne false, die est donc excute pour
dterminer le rsultat. Il en rsulte donc l'affichage du message d'erreur et l'arrt brutal du
script.

noter : L'oprateur = est prioritaire sur or, par consquent $link se verra attribuer la
valeur retourne par mysql_connect, et non le rsultat de l'opration logique.

Consquences

Lorsque la connexion au serveur choue (serveur indisponible, erreur de paramtrage), trois


choses se produisent :

1. Affichage d'un message d'erreur de la part de PHP, du type :


2. Warning:
3. mysql_connect() [function.mysql-connect]:
Can't connect to MySQL server on 'localhost' (10061) in fichier php
on line numro de ligne

4. Affichage du message "Impossible de se connecter au serveur MySQL"


5. Arrt du script

Les points 1 et 3 sont problmatiques. Le message d'erreur de PHP :

est disgrcieux,
fournit des informations "confidentielles" (nom du serveur, nom et chemin du fichier),
produit un affichage qui empche une ventuelle redirection / cration de cookie / etc.
(tout ce qui ncessite les enttes HTTP);

L'arrt du script :

invalide la page HTML (si du code a dj t produit, manqueront les balises de


fermeture des lments prcdemment ouverts; si aucun code n'a t produit, la "page"
ne dclare mme pas de doctype)
dnote un manque de professionnalisme en fournissant une page "bacle". Quand la
page se limite au message d'erreur brut, l'identit visuelle du site est perdue.

Ajoutons cela qu'un site proposant un service se doit d'tre courtois avec ses visiteurs, de
s'excuser platement pour la gne occasionne et de s'exprimer en termes comprhensibles.
vitons donc les messages allgrement copis-colls du type "Impossible de se connecter au
serveur MySQL" (demandez donc votre grand-mre si elle connait MySQL).

Oubliez galement les propositions visant contacter l'administrateur : vos internautes ont
autre chose faire, et vous tes dj (ou serez bientt) prvenus automatiquement ou par
consultation des logs.

Solutions

Tests avec if/else

En programmation procdurale avec le module mysql, il suffit de tester le retour des fonctions
qui sera false en cas d'chec.

$link = @mysql_connect('localhost', 'root', '');


if (!$link)
{
// Traitement de l'erreur
}
else
{
if (!@mysql_select_db('ma_base', $link)
{
// Traitement de l'erreur
}
else
{
$sql = 'SELECT champ1,champ2 FROM `ma_table`';
$rs = @mysql_query($sql, $link);
if (!$rs)
{
// Traitement de l'erreur
}
else
{
if (mysql_num_rows($rs) == 0)
{
// Traitement du cas o la requte n'a retourn aucun lment

}
else
{
// Exploitation des donnes
while ($row = mysql_fetch_assoc($rs))
{
// ...
}
}
}
}
}

Par commodit, j'utilise ici l'oprateur de gestion d'erreur @ pour annuler l'affichage des
messages d'erreur.

Pour plus d'informations sur la gestion des erreurs, voir le module correspondant sur php.net.

Utilisation de PDO

PDO est une interface pour accder une base de donnes depuis PHP partir de la version
5.1. PDO dfinit un driver spcifique pour chaque format de base (MySQL, Oracle, SQLite,
MS SQL, PostgreSQL...).

Pour initier une connexion travers PDO, on utilise :

<?php
$dbh = new PDO('mysql:host='.$host.';dbname='.$database, $user, $pass);
?>

La gestion des erreurs ventuelles se fait via l'emploi de blocs try {...} catch {...},
dans lesquels on place en premier les actions raliser, puis la gestion des erreurs (appeles
exceptions) si les instructions figurant dans try ont gnr une exception.

<?php
$NomServeur = $_SERVER['SERVER_NAME'] ;
$local = ( (substr($NomServeur, 0, 7) == '192.168') || ($NomServeur ==
'localhost') || (substr($NomServeur, 0, 3) == '127') );

$host = $local ? 'localhost' : 'xxxxxx';


$user = $local ? 'root' : 'xxxxxx';
$pass = $local ? '' : 'xxxxxx';
$database = $local ? 'test' : 'xxxxxx';
$verbose = $local;

try {
$dbh = new PDO('mysql:host='.$host.';dbname='.$database, $user, $pass);
foreach($dbh->query('SELECT * from table') as $row) {
// Traitement des rsultats
}
$dbh = null;
} catch (PDOException $erreur) {
if ($verbose) {
echo 'Erreur : '.$erreur->getMessage();
} else {
echo 'Ce service est momentanment indisponible. Veuillez nous
excuser pour la gne occasionne.';
}
}
?>
Ceci va de surcrot permettre d'exploiter les transactions SQL.

Classe wrapper du module mysql

Il s'agit d'englober les fonctions du module mysql dans une classe personnalise et de grer
soi-mme le comportement en cas d'action illgale. Cette pratique devient obsolte avec
l'apparition de PDO, mais peut se retrouver sur des projets anciens.

Conclusion

L'utilisation de or die(...) est trs pratique pour s'assurer qu'une commande SQL s'est bien
droule, mais elle implique une modification du code lors de la mise en ligne si l'on veut
produire des pages HTML valides en toutes circonstances. Cette pratique est donc proscrire
au profit de tests systmatiques ou d'utilisation de structures objets comme PDO.