# Programmation PHP/Exceptions

* Introduction
* Installer PHP
* Composer
* IDE
** PhpStorm
** NetBeans
** Eclipse
** Visual Studio Code
* Bases du langage
** Commentaires
** Premier programme
** Variables
** Variables superglobales
** Constantes
** Opérateurs
** Fonctions
** Tableaux
** Structures de contrôle
** Boucles
* Programmation avancée
** Dates
** Sessions
** Cookies
** Cache
*** Memcached
*** Redis
** Formulaire
** Fichiers
*** Objets COM
*** Images
** Mails
** Sécurité
** Programmation orientée objet
** Bases de données
*** Microsoft SQL Server
*** MySQL
*** PDO
*** SQLite
** Expressions rationnelles
** Code de haute qualité
*** Analyse statique de programmes
** Exceptions
** Xdebug
** Mots réservés
* Apprendre par l'exemple
** Utilisation de variables
** Un sommaire simple
** Interaction avec un formulaire
** Afficher le résultat d'une requête BDD
** Modifier une table
** Faire un livre d'or
** Faire un mini forum de discussion
** Parser avec DomXml
** Coder en MVC
** Faire un webservice
** Vérification RIO
** AJAX
** Sommaire en Ajax
** Mise à jour périodique d'un cadre
** Mini CMS
** Introduction
** Développement
*** Les couches choisies
*** Code de service
*** Modélisation
*** Implémentation
*** La vue
*** Ajaxification
*** Premier noyau
*** Fournir les données
*** IHM
** Rétrospective
** Conclusion
* Extensions PHP
** cURL
** DOMDocument
** JSON
** MING
** SPL
* Bibliothèques externes
** ADODB
** DOMPDF
** FPDF
** PHPExcel
** PHPMailer
** PHPWord
** RabbitMQ
* Cadriciels
** CakePHP
** PEAR
** Symfony
** Frameworks de tests
*** PHPUnit
*** SimpleTest
*** Behat
* Logiciels métier
* Problèmes connus
* Introduction
* Installer PHP
* Composer
* IDE
** PhpStorm
** NetBeans
** Eclipse
** Visual Studio Code
* Bases du langage
** Commentaires
** Premier programme
** Variables
** Variables superglobales
** Constantes
** Opérateurs
** Fonctions
** Tableaux
** Structures de contrôle
** Boucles
* Programmation avancée
** Dates
** Sessions
** Cookies
** Cache
*** Memcached
*** Redis
** Formulaire
** Fichiers
*** Objets COM
*** Images
** Mails
** Sécurité
** Programmation orientée objet
** Bases de données
*** Microsoft SQL Server
*** MySQL
*** PDO
*** SQLite
** Expressions rationnelles
** Code de haute qualité
*** Analyse statique de programmes
** Exceptions
** Xdebug
** Mots réservés
* Apprendre par l'exemple
** Utilisation de variables
** Un sommaire simple
** Interaction avec un formulaire
** Afficher le résultat d'une requête BDD
** Modifier une table
** Faire un livre d'or
** Faire un mini forum de discussion
** Parser avec DomXml
** Coder en MVC
** Faire un webservice
** Vérification RIO
** AJAX
** Sommaire en Ajax
** Mise à jour périodique d'un cadre
** Mini CMS
** Introduction
** Développement
*** Les couches choisies
*** Code de service
*** Modélisation
*** Implémentation
*** La vue
*** Ajaxification
*** Premier noyau
*** Fournir les données
*** IHM
** Rétrospective
** Conclusion
* Extensions PHP
** cURL
** DOMDocument
** JSON
** MING
** SPL
* Bibliothèques externes
** ADODB
** DOMPDF
** FPDF
** PHPExcel
** PHPMailer
** PHPWord
** RabbitMQ
* Cadriciels
** CakePHP
** PEAR
** Symfony
** Frameworks de tests
*** PHPUnit
*** SimpleTest
*** Behat
* Logiciels métier
* Problèmes connus
[ Modifier le sommaire ]

## 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 :

## 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 par 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.
Ces interruptions sont représentées par des classes qui héritent toutes du type Throwable, qui a deux classes filles : Error et Exception.

### Exemples

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 :
La bonne pratique est de ne jamais envoyer \Exception directement mais d'utiliser ses sous-classes, qui ont de plus généralement le bon code HTTP (au lieu de erreur 500). Par exemple sur Symfony, les erreurs inhérente à l'utilisateur (400) sont accessibles dans le namespace Symfony\Component\HttpKernel\Exception.
Par ailleurs, il est possible de créer ses propres classes d'exceptions, et de modifier les exceptions natives PHP avec set_exception_handler.

### Recréer une exception ou une erreur

Les Throwable PHP sont immutables, pour les modifier il faut donc les recréer. Pour faciliter cela, ils possèdent depuis PHP7 une méthode getPrevious, dont le résultat injecté en troisième argument du constructeur d'un autre, permet de cloner l'objet. Ex :
NB : la classe Throwable n'est pas instanciable directement.

## trigger_error

Cette fonction lance une exception du type placé en second paramètre, dont certains peuvent stopper l'exécution du programme. Par exemple :
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> :
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 :
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_backtrace et debug_print_backtrace

Ces fonction affichent automatiquement la trace de l'exécution menant à elles.
Sur un framework cela peut être trop long à exécuter, il faut donc ne faire afficher que les noms des fichiers exécutés avec l'argument suivant :

#### throw

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

#### Exception::getTraceAsString

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

### Fichier de log maison

Bien souvent on ne peut pas afficher les logs dans le navigateur ou rapidement via le logeur existant, donc il faut recourir à la création d'un nouveau fichier de log temporaire :

### Symfony

Depuis une commande Symfony, on peut afficher des logs en console :
Mais le mieux est d'utiliser la bibliothèque Monolog (compatible PSR-3), pour que les logs soient horodatés et 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 (ce qui est fait par défaut sur la v3.3 dans config/packages/dev/monolog.yaml).
Pour booster ses performances, on peut le régler ainsi dans monolog.yaml :
Quand l'application tourne sur plusieurs serveurs frontaux, il vaut mieux centraliser les logs dans un agrégateur de logs comme Kibana ou Graylog. Or, dedans il est possible que tous les logs ne soient pas visibles. Par exemple en cas de caractères spéciaux dans les clés des tableaux, tels que ">" ou "$", ou en cas de valeur NULL :

## Références

* ↑ https://www.php.net/manual/fr/language.errors.php7.php
* ↑ http://php.net/manual/fr/function.set-exception-handler.php
* ↑ http://php.net/manual/fr/function.trigger-error.php
* ↑ https://symfony.com/doc/current/logging.html
* ↑ https://www.php-fig.org/psr/psr-3/
* ↑ https://symfony.com/doc/current/logging/monolog_console.html