« Programmation PHP/Exceptions » : différence entre les versions

Un livre de Wikilivres.
Contenu supprimé Contenu ajouté
m mot en double
Ligne 129 : Ligne 129 :


=== Symfony ===
=== Symfony ===
Depuis une une commande Symfony, on peut afficher des logs en console :
Depuis une commande Symfony, on peut afficher des logs en console :
<source lang=php>
<source lang=php>
$output->writeln('Update complete');
$output->writeln('Update complete');

Version du 20 septembre 2019 à 11:17

Tester l'existence

Pour éviter les warnings de variables inexistantes il vaut mieux les initialiser au début. Si toutefois cela s'avère impossible, on recourt à des tests sur les fonctions suivantes pour le faire :

if (!isset($maVariable)) { $maVariable = ''; }
if (!defined('MA_CONSTANTE')) { define('MA_CONSTANTE', ''); }
if (!function_exists('maFonction')) { function maFonction() {} }

empty()

Permet de savoir si une variable est définie et si contient une valeur. Son comportement s'adapte au type de la variable. Cela équivaut à :

  • String : isset($v) and $v == "".

ou

  • Booléen : isset($v) and $v == false.

ou

  • Tableau : isset($v) and sizeof($v) == 0.

try... catch

Tout comme en Java, la levée d'exception est assurée un bloc try... catch. Cela permet à un script de poursuivre son exécution malgré les erreurs (ex : panne réseau), et ainsi de ne pas bloquer l'utilisateur sur une page blanche ou en anglais destinée au développeur.

Exemple :

try {
  echo '1 / 2 = ' 1/2;
  echo '3 / 0 = ' 3/0; // instruction qui déclenchera l'exception
  echo '2 / 1 = ' 2/1; // cette instruction ne sera pas exécutée à cause de la précédente
}
catch (Exception $e) {
  echo $e->getMessage(); // afficher le message lié à l'exception
}

Il n'est donc pas nécessaire de prévoir ce qui peut interrompre le programme pour s'en prémunir et poursuivre l'exécution en fonction.

La classe de gestion des erreurs nommée Exception est gracieusement mise à votre disposition par l’interpréteur dans les versions ultérieures à PHP 5.0.

Autre exemple d’utilisation :

class Humain
{
  var $age;

  function __construct($combien)
  {
    $this->age = $combien;
   
    try {
      if ($this->age<0)
      throw new Exception('Un peu jeune');
      if ($this->age>200)
      throw new Exception('Un peu vieux');
    } catch (Exception $e) {
      echo $e->getMessage();
      return;
    }
  }

}

//Retournera un message d'erreur
$humain = new Humain(700);
$humain = new Humain(-3);

//Sans erreur
$humain = new Humain(16);

Par ailleurs, il est possible de modifier les exceptions PHP avec set_exception_handler()[1].

trigger_error()

Cette fonction lance une exception du type placé en second paramètre, dont certains peuvent stopper l'exécution du programme[2]. Par exemple :

  trigger_error("Message d'erreur", E_USER_ERROR);

Affiche : ErrorException. User Error: Message d'erreur.

La liste des types d'erreur est disponible sur http://php.net/manual/fr/errorfunc.constants.php.

Logs

Affichage d'une trace lisible

Afin de clarifier la trace de l'exécution des scripts, il peut être utile de formater celle-ci avec la balise <pre> :

if ($debogage) {
  print '<pre>';
  var_dump(scandir('.'));
  print '</pre>';
}

NB : on rappelle que les commandes ini_set('display_errors', 1); et error_reporting(E_ALL); permet d'afficher à l'écran toutes les erreurs et avertissements.


Voici une manière de n'afficher les erreurs que lors du débogage :

if ($debogage) {
  error_reporting(E_ALL);
} else {
  error_reporting(0);
}

Pour créer une bonne gestion des erreurs, partez du principe que l'utilisateur est imprévisible, et qu'il va justement faire ce qu'il ne faut pas (Loi de Murphy). Envisagez toutes les possibilités et trouvez-y une solution, en testant les exceptions (ex : caractères d'échappements ou symboles non ASCII comme des sinogrammes pour voir s'ils s'affichent bien).


debug_print_backtrace

Cette fonction affiche automatiquement la trace de l'exécution menant à elle.

Logo

sur un framework elle peut être trop longue à exécuter, il faut donc ne lui faire afficher que les noms des fichiers exécutés.

echo '<pre>'; debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);echo '</pre>';

throw

Si l'affichage de la trace doit être suivi d'une interruption du programme, utiliser :

throw new \Exception('Trace');

Exception::getTraceAsString()

Si l'exception ne surgit pas avec un throw, on peut afficher la trace depuis avec sa méthode :

echo $e->getTraceAsString();

Symfony

Depuis une commande Symfony, on peut afficher des logs en console :

$output->writeln('Update complete');

Mais le mieux est d'utiliser la bibliothèque Monolog[3] (compatible PSR-3[4]), pour que les logs s'enregistrent dans var/log/ (puisque les commandes peuvent être lancées par cron et donc sans affichage en console). De plus, Monolog est configurable pour afficher en plus ces logs en console[5] (ce qui est fait par défaut sur la v3.3 dans config/packages/dev/monolog.yaml).

composer require symfony/monolog-bundle

Xdebug

Xdebug est un système qui permet d'exécuter le code pas à pas, et élimine donc le risque de sauvegarder des "echo", des "print" ou des "var_dump" en production.

Installation

Installation sur Linux[6][7] :

sudo apt-get install php7.2-xdebug

ou

pecl install xdebug

Puis dans php.ini, sur PHP7.0 :

xdebug.remote_enable = On

ou sur PHP7.2 :

sudo vim /etc/php/7.2/apache2/conf.d/20-xdebug.ini

Ajouter :

xdebug.remote_enable=1

Configuration complète

On peut aussi forcer d'autres paramètres[8] :

sudo apt-get install php7.2-xdebug
&& echo "xdebug.remote_enable=1" >> /usr/local/etc/php/php.ini \
&& echo "xdebug.remote_handler=dbgp" >> /usr/local/etc/php/php.ini \
&& echo "xdebug.remote_connect_back=0" >> /usr/local/etc/php/php.ini \
&& echo "xdebug.remote_port=9000" >> /usr/local/etc/php/php.ini \
&& echo "xdebug.remote_autostart=1" >> /usr/local/etc/php/php.ini

Avec Docker, il faut aussi spécifier le "remote_host"[9].

Lancement

Dans un navigateur

Il faut installer un module sur son navigateur (ex : Xdebug-ext sur Firefox[10]) pour pouvoir activer ou désactiver le débogage d'une page. Ce module s'interface avec les principaux IDE, par exemple PhpStorm, pour leur faire lancer le débogage lors du chargement d'une page.

En ligne de commande

On peut ajouter un argument à PHP[11]. Ex :

php -d xdebug.profiler_enable=1 bin/console MaCommande.php

Utilisation

Lors du débogage, Phpstorm fera apparaitre un menu "Debug" avec trois sous-menus dont :

  1. la liste des variables du script et leurs valeurs (modifiables à la volée)
  2. les warnings PHP
  3. la sortie HTML.

Quand on clique dans la marge, un point d’arrêt est créé et représenté par une ligne rouge.

Raccourcis clavier (voir le menu "Run" en haut) :

  • F7 (step into) : mode pas à pas détaillé.
  • F8 (step over) : mode pas à pas sans sauter dans les dépendances.
  • F9 (resume) : poursuivre l'exécution du programme sans s'arrêter.
  • Alt + F9 : poursuivre jusqu'au prochain point d'arrêt.
  • Shift + F7 : pas à pas intelligent.

Références