[PHP] Utiliser un débogueur pour PHP : Xdebug

Formation

En Semi-présenciel Paris

Prix sur demande

Appeler le centre

Avez-vous besoin d'un coach de formation?

Il vous aidera à comparer différents cours et à trouver la solution la plus abordable.

Description

  • Typologie

    Formation

  • Méthodologie

    En semi-présentiel

  • Lieu

    Paris

Grâce à cette formation vous pourrez acquérir les connaissances nécessaires qui vous permettrons d’ajouter des compétences à votre profil et obtenir de solides aptitude qui vous offriront de nombreuses opportunités professionnelles.

Les sites et dates disponibles

Lieu

Date de début

Paris ((75) Paris)
Voir plan
7 Cité Paradis, 75010

Date de début

Consulter

Questions / Réponses

Ajoutez votre question

Nos conseillers et autres utilisateurs pourront vous répondre

À qui souhaitez-vous addresser votre question?

Saisissez vos coordonnées pour recevoir une réponse

Nous ne publierons que votre nom et votre question

Les Avis

Le programme

Introduction du cours

Les débogueurs (ou outils de débogage) sont assez méconnus du grand public ou mal utilisés.
Xdebug en est un et son utilisation permet d'accélérer et de simplifier efficacement les cycles de déboguage d'une application PHP.
Comment l'installer, le configurer et l'utiliser ? Qu'apporte-t-il ?
Voilà ce que tentera d'expliquer ce tutoriel.

Historique du tutoriel :

  • 19/12/2008 : Démarrage de la rédaction du tutoriel.

  • 07/02/2009 : Validation du tutoriel.

  • 08/05/2009 : Première mise à jour: ajout d'informations pour l'installation.

  • À venir : Intégration dans un IDE.

Un débogueur, l'outil de l'efficacitéPrésentation rapide

Xdebug est une extension initialement apparue pour PHP4 et dans sa version 2.0.x n'est compatible que pour PHP 4.4.x et supérieur. Elle est disponible sur PECL et est donc codée en C (contrairement aux extensions présentes sur le dépôt PEAR qui elles sont codées en PHP).

Une extension écrite en C sera toujours plus rapide que si elle était écrite en PHP.

Xdebug permet de déboguer facilement son script, mais génère aussi des fichiers de trace et surtout gère le profiling. Ces derniers interviennent dans la phase d'optimisation d'une application plutôt que dans le débogage pur (le profiling ne se fait que si le script fonctionne). Un bien joli programme pour un outil qui accélèrera vos développements ;) .

Cette extension personnalise les messages d'erreur en y ajoutant toute la pile des appels de fonctions et de classes. De plus elle permet d'y ajouter des informations sur la mémoire ou sur l'état des variables :p ...
Exemple :

Devient :

Avant tout sachez que Xdebug n'est pas le seul outil de débogage pour PHP : il existe aussi APD, DBG...

L'installationPour les systèmes UNIX :

Pour les systèmes UNIX il faut installer PEAR. Cette installation diffère selon les distributions, renseignez-vous sur le site de PEAR : http://pear.php.net/.

Pour la plupart des distributions, faites :

sudo apt-get install php-pear

Et sudo apt-get install php5-dev, si le paquet n'est pas déjà installé.

Puis lancez la commande suivante :

sudo pecl install xdebug

Et laissez PECL faire le reste. ;)

Si l'installation depuis PECL ne fonctionne pas il vous faudra compiler Xdebug manuellement. Reportez-vous à la documentation de Xdebug.

Pour Windows :

Pour Windows il faut récupérer la DLL ici : http://www.xdebug.org/download.php.
Prenez la version de Xdebug correspondant à votre version de PHP et la plus récente possible de préférence.
Puis mettez la DLL dans le répertoire d'extension de votre serveur (généralement appelé "ext").

Le démarrage

Pour faire démarrer Xdebug avec le serveur, ajoutez ceci à votre fichier php.ini :

zend_extension=/chemin/vers/xdebug.so

Le chemin correspond à celui des extensions, il est indiqué lors de l'installation par Pecl:

Vous pouvez aussi trouver le chemin en faisant find -name 'xdebug.so'.

Ou pour Windows :

zend_extension_ts=/chemin/vers/xdebug.dll

Puis redémarrez le serveur.

Si vous avez une erreur avec zend_extension(_ts) utilisez seulement extension mais Xdebug n'est plus alors chargé en tant qu'extension Zend.

C'est-à-dire qu'il n'est pas directement intégré dans le Zend Engine (moteur de PHP) et certaines fonctionnalités peuvent ne pas fonctionner.
Par exemple sous Wamp faites comme ceci :

zend_extension_ts=C:\wamp\bin\php\php5.2.8\ext\php_xdebug.dll

Si vous faites un phpinfo() vous devriez voir ceci (notez que Xdebug s'active par défaut) :

Son utilisation basiqueEncore et toujours de la configurationQuelques paramètres de configuration

Vous pouvez configurer Xdebug depuis le php.ini ou depuis votre script (personnellement je préfère la première solution ;) ).
Ajoutez-y par exemple ceci :

[Xdebug] ;xdebug.default_enable=Off xdebug.show_local_vars=1

N'oubliez pas de redémarrer le serveur après chaque modification du php.ini.

Par défaut, Xdebug est activé automatiquement (xdebug.default_enable=On ), la directive xdebug.show_local_vars=1 permet de visualiser les variables locales de la partie du code qui provoque l'erreur.
Testez cela avec ce code des plus basiques (je crois qu'il se passe d'explication :-° ) :

<?php $a = 25; $b = "25"; $c = array(25); $d = array('25'); // Et une notice, une ... echo $var; $e =(string) $a.$b; // Encore une notice. echo $var; ?>

Ceci donne cela (là aussi je vous dispense d'explications) :

Si vous n'obtenez pas de notice, vérifiez votre niveau de rapport d'erreur qui doit intégrer les notices. En développement utiliser E_ALL ou E_STRICT (PHP 5) est nettement recommandé. Pour ce faire fixez-le dans le php.ini ou à la volée avec error_reporting() .

Si pour une raison quelconque vous n'avez pas accès au fichier php.ini, vous pouvez soit utiliser la fonction correspondante au paramètre voulu si elle existe (par exemple : xdebug_enable() ) soit utiliser la fonction ini_set() .

Pour démarrer Xdebug vous pouvez utiliser la fonction xdebug_enable() ainsi que xdebug_is_enabled() pour savoir si Xdebug est démarré.
Vous pouvez activer xdebug.show_local_vars avec ini_set :

Citation : Documentation

string ini_set ( string $varname , string $newvalue )

Donc :

<?php ini_set('xdebug.show_local_vars', 1); ?>

Avec le code plus haut, ini_set('xdebug.show_local_vars', 1) ne fonctionnera pas.
Ceci est dû au fonctionnement de PHP : lorsque le client fait une requête au serveur pour une page PHP, le Zend Engine parse et compile le code en opcodes (compilation qui peut être coûteuse en ressources d'où l'intérêt des outils de cache d'opcodes, cherchez APC, APD...). Or Xdebug est intégré au Zend Engine donc même si la compilation échoue il s'exécute. Mais ici avant l'exécution du main du code PHP qui configure xdebug.show_local_vars=1 ce paramètre est assigné à 0 et la Notice est générée donc l'affichage des variables ne se fait pas.

Testez avec ce code :

<?php ini_set('xdebug.show_local_vars', 1); // Code compilé en opcodes avant cet appel. set_time_limit(1); function foo($a){ while($a > 0) $a++; // Boucle infinie, erreur ici donc Xdebug indique seulement cette variable. } $a = 25; $b = "25"; $c = array(25); $d = array('25'); $e = foo($a); ?> Les variablesLa fonction var_dump()...

La fonction var_dump() est très utile pour le débogage car elle donne beaucoup d'informations sur l'état d'une variable. Mais Xdebug permet de modifier la sortie de var_dump().
Testons pour voir un exemple modifié de la documentation :

<?php if(function_exists('xdebug_enable'))         xdebug_disable( ); $a = array(1, 2, array("a", "b", "c")); $b = 3.1; $c = true; var_dump($a); var_dump($b, $c); echo '<hr />'; xdebug_enable( ); var_dump($a); var_dump($b, $c); ?>

À priori aucun changement notable... J'ai bien dit à priori parce que si vous testiez en désactivant le chargement de l'extension depuis le php.ini vous verriez la différence ^^ . Donc Xdebug modifie bien la sortie de var_dump().

Illustrations :
Avec Xdebug chargé dans le php.ini :

Et sans :

Bien sûr, utiliser les balises <pre></pre> permettrait un meilleur affichage mais c'était juste pour contraster ;) .

Mais, il ne fait que modifier la sortie pour la rendre plus lisible ?

Non, Xdebug permet aussi de modifier le nombre d'enfants, de valeurs et de niveaux affichés pour un array ou un objet (pour plus de détails consultez la doc).

...et un dump fort utile

Xdebug permet aussi d'afficher l'état des variables superglobales ce qui est quand même pratique dans le cadre du débogage.
Pour cela il faut modifier le php.ini avec xdebug.dump.VARIABLE=[* ou NOM VARIABLE] . Par exemple pour afficher toutes les variables GET, l'adresse IP de l'utilisateur et le nom du serveur, on fait comme ceci :

xdebug.dump.GET=* xdebug.dump.SERVER=REMOTE_ADDR, SERVER_NAME

Les autres superglobales possibles sont, en plus de GET et SERVER, POST, COOKIE, FILES, REQUEST et SESSION.

Plus on ajoute de paramètres à Xdebug plus le rapport d'erreur sera long, il faut donc y faire attention si on ne veut pas se retrouver avec des valeurs inutiles. C'est pourquoi le symbole * est à utiliser avec précaution.

Les variables SERVER ne sont affichées que si elles sont utilisées dans le code (ceci est le cas depuis 2.0.2 bug ou non ?). En appelant le code suivant avec "test=string&amp;test2=2" comme paramètres, on obtient l'image qui le suit :

<?php $a = array(1, 2, array("a", "b", "c")); $b = 3.1; $c = true; $_SERVER['SERVER_NAME']; // Intervention d'une variable serveur dans le code. var_dump($a); var_dump($b, $c); echo $var; // Notice ?> Le traçageLa pile d'appel

Rentrons maintenant dans le vif du sujet avec une fonction de Xdebug qui se révèle très utile : j'ai nommé la pile d'appel. Cette pile indique tous les appels de fonctions et de classes.
Prenons par exemple le code suivant :

<?php set_time_limit(5); function error($var){         $buffer = 0;         while($var = 1){                 $buffer += $var;                $var--;         }      return $buffer; } error(5); ?>

Le code va produire une boucle infinie du fait d'une erreur courante qui est l'utilisation du égal '=' d'assignation au lieu du égal '==' de comparaison.
Or désormais plus besoin de venir poster sur le bien-aimé forum PHP du Site du Zéro avec en titre "Alerte PHP ne m'aime pas" :p , car si vous utilisez Xdebug l'erreur sera des plus claires.
Voyons le tout en images !

  • Si Xdebug n'est pas activé PHP retourne l'erreur :

    Citation

    Fatal error: Maximum execution time of 5 seconds exceeded in C:\wamp\www\tutos\xdebug\erreur.php on line 42

    (Eh oui j'ai limité le temps à 5 sec pour vous éviter le long délai d'attente de 30 secondes.)

  • Si Xdebug est activé on obtient ceci :

Xdebug renvoie la même erreur que PHP mais si on regarde la pile des appels, on remarque que le script est resté sur error() jusqu'à la fin du script qui a duré trop longtemps. De plus on peut voir la valeur astronomique qu'a prise la variable $buffer.

Un cas plus concret de la pile d'appel est celui des premières images du tutoriel où elle nous permet de savoir d'un seul coup où l'exception a été lancée :

Devient :

Un autre exemple :
Le cas d'une fonction récursive dont l'algorithme est mal conçu (dans notre cas très mal conçu ^^ ). La voici donc :

<?php set_time_limit(5); function recursive_error($param){         if(!$param) return 1;         return $param * recursive_error($param + 1);  //au lieu de $param - 1 } recursive_error(10); ?>
  • Sans Xdebug le script est instable et produit une erreur.

  • Avec Xdebug activé on obtient l'erreur ci-dessous :

    La pile d'appel est des plus claires, la fonction recursive_error() s'appelle indéfiniment.

Cet exemple me permet de parler d'une autre particularité de Xdebug : les traces...

Quand on parle de traces

Il est rare que l'on obtienne une fonction récursive qui s'appelle indéfiniment mais il peut arriver par exemple qu'elle accomplisse des occurrences non voulues. C'est pour ce genre de raison que l'on peut se servir des traces lorsque l'on veut suivre, tracer, une fonction.

Activer les traces

Activons tout d'abord les traces et paramétrons-les, voici ce que vous pouvez ajouter au php.ini :

xdebug.auto_trace=1 xdebug.trace_output_dir="chemin\vers\dossier\trace\"

En ajoutant ces quelques lignes (et bien sûr en redémarrant le serveur) les traces seront activées automatiquement et ces fichiers s'enregistreront dans le répertoire spécifié.

Dans ce cas-ci ini_set() ne fonctionne pas car l'exécution automatique doit être faite avant l'appel du script principal (main). C'est pourquoi il faut utiliser la fonction xdebug_start_trace() , expliquée plus bas, qui combine xdebug.auto_trace=1 et xdebug.trace_output_dir="chemin\vers\dossier\trace\" .

Exécutons de nouveau notre fonction récursive, nous obtenons le fichier log de trace suivant :

TRACE START [2008-12-23 11:08:09]     0.0007      64152   -> {main}() C:\wamp\www\tutos\xdebug\erreur.php:0...

Appeler le centre

Avez-vous besoin d'un coach de formation?

Il vous aidera à comparer différents cours et à trouver la solution la plus abordable.

[PHP] Utiliser un débogueur pour PHP : Xdebug

Prix sur demande