Oups! Erreurs PHP pour Cool Kids

Whoops est une petite bibliothèque, disponible sous forme de package Composer, qui vous aide à gérer les erreurs et les exceptions dans vos projets PHP..

Hors de la boîte, vous obtenez une page d'erreur élégante, intuitive et informative chaque fois que quelque chose se passe dans votre application. Mieux encore, dans tout cela, il s'agit d'un ensemble d'outils très simples, mais flexibles, permettant de traiter les erreurs d'une manière qui a du sens pour tout ce que vous faites..

Les principales caractéristiques de la bibliothèque sont:

  • Page détaillée et intuitive pour les erreurs et les exceptions
  • Affichage du code pour toutes les images
  • Concentrez-vous sur l'analyse des erreurs / exceptions grâce à l'utilisation de middleware / gestionnaire simples et personnalisés
  • Prise en charge des requêtes JSON et AJAX
  • Fournisseurs inclus pour les projets Silex et Zend par l’intermédiaire des fournisseurs groupés, et inclus dans Laravel 4 core
  • Base de code propre, compacte et testée, sans dépendances supplémentaires

Whoops y parvient grâce à un système de gestionnaires empilés. Vous indiquez à Whoops les gestionnaires que vous souhaitez utiliser (vous pouvez choisir parmi les gestionnaires inclus ou créer le vôtre), et si quelque chose se produit, tous les gestionnaires reçoivent, dans l’ordre, une chance de faire quelque chose - cela peut être quelque chose d’analyser le error (Whoops facilite l’extraction d’informations significatives d’une erreur ou d’une exception) et à l’affichage d’écrans d’erreur utiles (comme le PrettyPageHandler, qui vous donne la page cool à la recherche ci-dessus).

Essayons d'abord, en regardant les bases, puis en essayant de construire notre propre gestionnaire avec Whoops et le framework Laravel. Pour ce petit guide, je suppose que vous êtes relativement à l'aise avec PHP et que vous avez entendu parler de Composer. Si ce n'est pas le cas, lisez-le ici chez Nettuts+.


Installation de Whoops

Créez un répertoire pour votre projet, changez-le, créez un composer.json fichier avec l'exigence Whoops et installez-le. Whoops (à partir de la version 1.0.5) n'a pas de dépendances, cela ne prendra donc qu'une seconde.

 $ cd / chemin / vers / votre / projet $ composeur nécessite filp / whoops 1. * $ composer install

Utiliser Whoops: l'essentiel

Pour voir cette page d'erreur élégante en action, configurons Whoops et faisons en sorte que quelque chose se brise en lançant une exception dans notre code. Créez un fichier dans le répertoire de votre projet. pour ce guide, disons qu'il s'appelle, index.php.

 $ cd / chemin / vers / votre / projet $ votre-éditeur-favori index.php

Comme nous avons installé Whoops avec Composer et qu'il est compatible PSR-0, tout ce que nous avons à faire est de requérir l'autochargeur Composer et nous sommes prêts à commencer à utiliser la bibliothèque dans notre propre code.!

 pushHandler (new Whoops \ Handler \ PrettyPageHandler ()); // Définit Whoops comme gestionnaire d'erreur et d'exceptions par défaut utilisé par PHP: $ whoops-> register (); lance la nouvelle RuntimeException ("Oopsie!"); ?>

Si vous avez déjà un serveur Web en cours d'exécution, allez-y et accédez au fichier que vous venez de créer. N'oubliez pas: si vous utilisez PHP 5.4, vous pouvez utiliser le serveur de développement intégré, comme ceci:

 $ cd / chemin / vers / votre / projet $ php -S localhost: 8080

Voici ce que vous obtiendrez:

Plutôt chouette, non? Les gestionnaires, eux-mêmes, peuvent exposer des options pour modifier ou améliorer leur comportement. Par exemple, vous pouvez notamment définir le titre de la page d'erreur par défaut et même insérer des informations supplémentaires:

 setPageTitle ("C'est cassé!"); // Définit le titre de la page $ errorPage-> setEditor ("sublime"); // Définit l'éditeur utilisé pour le lien "Ouvrir" $ errorPage-> addDataTable ("Extra Info", array ("stuff" => 123, "foo" => "bar", "utile-id" => "baloney ")); $ whoops-> pushHandler ($ errorPage); $ whoops-> register (); lance la nouvelle RuntimeException ("Oopsie!"); ?>

De plus, comme il s’agit simplement d’un gestionnaire Whoops standard, nous pouvons combiner ces derniers avec d’autres gestionnaires pour obtenir des résultats plus dynamiques. Imaginons que vous travailliez sur un site Web géré par AJAX + JSON. À l'heure actuelle, si votre application échouait d'une manière ou d'une autre, vous auriez un tas de codes HTML vilain à venir, lorsque vous vous attendiez à JSON. Pas grave:

 pushHandler (new Whoops \ Handler \ PrettyPageHandler ()); $ whoops-> pushHandler (new Whoops \ Handler \ JsonResponseHandler ()); $ whoops-> register (); lance la nouvelle RuntimeException ("Oopsie!");

C'est tout. Désormais, si quelque chose échoue lors d'une requête AJAX, Whoops répondra par une réponse JSON détaillant l'erreur. S'il ne s'agit PAS d'une demande AJAX, vous continuerez à voir la page d'erreur habituelle. Si une erreur se produit, Whoops filtrera tous les gestionnaires enregistrés (en commençant par le dernier gestionnaire enregistré) et leur donnera l'occasion d'analyser, de modifier et de répondre à la demande..

Maintenant que vous avez une idée générale du fonctionnement de Whoops, essayons de construire notre propre gestionnaire avec Whoops et le framework Laravel 4.


Oups et Laravel 4

Laravel 4 bundles Whoops en tant que gestionnaire d'exceptions principal, activé par défaut en mode de développement, y compris un jeu de couleurs personnalisé par Dayle Rees:

Si vous n'avez pas encore installé Laravel, continuez et suivez les étapes d'installation. Laravel est largement couvert par Nettuts + et Tuts + Premium. Vous y trouverez donc beaucoup de formation si vous souhaitez approfondir vos connaissances..

Pour les prochaines étapes, je suppose que vous êtes quelque peu à l’aise avec les bases de Laravel 4. Toutefois, même si vous ne l’êtes pas, il devrait quand même être facile à suivre..

Si vous êtes en mode développement (débogage), Whoops est disponible via le conteneur IoC en tant que oups, et pré-réglé avec l'un des deux gestionnaires: PrettyPageHandler ou JsonResponseHandler, comme whoops.handler (les deux mêmes dont nous venons de parler). Ces deux gestionnaires exposent des méthodes supplémentaires utiles, comme vous l'avez vu plus haut avec PrettyPageHandler. En accédant à ces services, nous pouvons commencer à personnaliser notre expérience Whoops dans le cadre.

Par souci de simplicité, dans votre app / routes.php fichier, connectons-nous au service Whoops et définissons un titre de page personnalisé pour nos pages d'erreur:

 setPageTitle ("Houston, nous avons un problème!"); // Définissez le lien "open:" pour les fichiers vers notre éditeur de choix: $ whoopsDisplayHandler-> setEditor ("sublime");  Route :: get ('/', function () // Forcer l'exécution à échouer en lançant une exception: throw new RuntimeException ("Oopsie!");); ?>

Pointe: Whoops supporte quelques éditeurs par défaut et vous permet de mettre en place le support que vous souhaitez. En savoir plus à ce sujet ici.

Si vous accédez maintenant à votre application Laravel, vous recevrez un message d'erreur avec le titre de votre page personnalisée. Si vous cliquez sur le chemin du fichier au-dessus de la zone de code, le fichier référencé devrait s'ouvrir directement dans l'éditeur ou l'EDI de votre choix. À quel point cela est cool? De plus, étant donné que nous pouvons atteindre le gestionnaire déjà configuré par le noyau Laravel, nous pouvons utiliser les autres fonctionnalités décrites ci-dessus. Par exemple, nous pouvons ajouter des tables personnalisées (avec PrettyPageHandler :: addDataTable) avec des informations utiles sur notre application.

Essayons un autre exemple. Ce sera notre première tentative d'écriture de notre propre gestionnaire personnalisé. Nous voulons obtenir tous les cadres de pile pour une exception et supprimer tout ce qui ne fait pas partie de notre code d'application. Cela semble assez simple, à droite?

 pushHandler (function ($ exception, $ exceptionInspector, $ runInstance) // Récupère la collection de cadres de la pile pour l'exception en cours: $ frames = $ exceptionInspector-> getFrames (); // Filtre les cadres existants de manière à ne conserver que ceux à l'intérieur. app / folder $ frames-> filter (function ($ frame) $ filePath = $ frame-> getFile (); // correspond à tout chemin de fichier contenant / app /… return preg_match ("/ \ / app \ /.+ / i ", $ filePath);); return Handler :: DONE;);  Route :: get ('/', function () // Forcer l'exécution à échouer en lançant une exception: throw new RuntimeException ("Oopsie!");); ?>

Pointe: Vous n'êtes pas obligé de revenir Gestionnaire :: DONE - cela ne sert qu’à des fins sémantiques. Si vous souhaitez que Whoops arrête de lancer des gestionnaires supplémentaires après le vôtre, écrivez à return Handler :: LAST_HANDLER. Si vous voulez que Whoops quitte l'exécution du script après votre gestionnaire, gestionnaire de retour :: QUIT.

Vous pouvez voir que c'est remarquablement concis. Whoops \ Runde PushHandler method accepte une fermeture qui reçoit jusqu'à trois arguments: l'objet exception, un inspecteur d'exception, qui expose certaines méthodes utilitaires pour, vous l'aurez deviné, inspecter les exceptions, et Whoops \ Run instance qui a capturé l'exception. Grâce à ce gestionnaire, nous utilisons l’inspecteur des exceptions pour extraire les cadres de la pile, le tout dans un environnement soigné. FrameCollection objet:

 getFrames (); // # => Whoops \ Exception \ FrameCollection; compter ($ images); # => int foreach ($ cadres en tant que $ cadres) get_class ($ cadres); // # => Whoops \ Exception \ Frame print $ frame-> getFile (). ":". $ frame-> getLine (). "\ n"; # => "/path/to/file.php:123"?>

Pointe: Whoops convertit en interne les fermetures en un gestionnaire spécial: Whoops \ Handler \ CallbackHandler.

Vous pouvez compter, itérer, cartographier et filtrer le contenu de cette classe, avec l’aspect intéressant mais important que les opérations de cartographie et de filtrage mutent l’objet sur place. Cela signifie que ces deux opérations modifient l'instance d'origine directement, au lieu de créer une nouvelle collection. Comment est-ce important? Cela signifie que les gestionnaires peuvent plus facilement effectuer des modifications qui se propagent vers le bas à tous les autres gestionnaires de la pile. C'est exactement ce que nous avons fait avec notre gestionnaire simple ci-dessus. Si vous exécutez à nouveau le script, vous verrez que nous obtenons une liste plus courte de cadres de pile, ne concernant que le code résidant dans notre répertoire d'application..

Quant à l’objet Frame, lui-même (Whoops \ Exception \ Frame), il expose un ensemble de méthodes permettant de collecter des informations sur le contenu du cadre (chemin du fichier, numéro de ligne, appel de méthode ou de fonction, nom de classe, etc.) et de méthodes permettant d’attacher des commentaires à des cadres de pile individuels. Whoops est une fonctionnalité utile dans Whoops qui permet aux gestionnaires de fournir des informations supplémentaires qu'ils collectent à partir d'une exception en attachant des notes directement aux images individuelles de la pile. Les manutentionnaires aiment le PrettyPageHandler, par exemple, peut ensuite rassembler ces commentaires et les afficher avec le chemin d'accès au fichier et le numéro de ligne du cadre.

 pushHandler (function ($ exception, $ exceptionInspector, $ runInstance) foreach ($ exceptionInspector-> getFrames () en tant que $ i => $ frame) $ frame-> addComment ("Ceci est le numéro de frame $ i");  return Handler :: DONE;); ?>

Les commentaires de cadre peuvent également recevoir une seconde portée argument. Si vous avez plusieurs gestionnaires personnalisés, vous pouvez, par exemple, filtrer les commentaires de cadre par cet argument pour ne rassembler que les informations qui vous intéressent..

 getFrames (); foreach ($ frames as $ frame) // Ce cadre était-il dans une classe de contrôleur? (se termine dans Controller) $ className = $ frame-> getClass (); if (substr ($ className, -10) == "Controller") $ frame-> addComment ("Cette trame est à l'intérieur d'un contrôleur: $ className", "controller-error");  // Plus tard, dans un autre gestionnaire, obtenez tous les commentaires dans l'étendue 'erreurs de contrôleur': $ controllerErrors = $ frame-> getComments ("controller-errors"); // # => tableau?>

Également d’intérêt, le PrettyPageHandler Naturellement, HTML échappe aux commentaires du cadre avant de les afficher, mais capturera intelligemment les URI dans le corps du commentaire et les convertira en éléments d'ancrage cliquables. Vous souhaitez lier des cadres à la documentation ou à des référentiels GitHub? C'est assez facile; Créons notre propre classe de gestionnaire pour cet exemple.

Pointe: Utiliser votre propre classe au lieu d'une fermeture vous donne un contrôle supplémentaire sur votre gestionnaire, sans oublier de le rendre plus facile à couvrir avec des tests automatisés. Vos classes de gestionnaires personnalisés doivent implémenter le Whoops \ Handler \ HandlerInterface interface, mais vous pouvez simplement étendre la Whoops \ Handler \ Handler classe, et mettre en œuvre les manquants manipuler méthode, comme indiqué dans l'exemple ci-dessous.

 getInspector () -> getFrames (); foreach ($ frames en tant que $ frame) $ file = $ frame-> getFile (); $ line = $ frame-> getLine (); // Certaines images peuvent ne pas avoir de chemin de fichier, par exemple, si cela se produit dans // une fermeture, nous devrons donc vérifier cela: if (! $ File) continue; // Vérifiez si le chemin du fichier pour cette image se trouvait dans le répertoire laravel / framework //, dans le répertoire Composer vendor /, et utilisez une capture de regex // pour extraire uniquement les parties souhaitées: if (preg_match ("/ \ / fournisseur \ / laravel \ / framework \ / (. +) $ / ", $ fichier, $ correspond)) $ chemin = $ correspond [1]; // La première correspondance est un chemin complet, la seconde est notre capture $ url = "$ this-> repoBase / $ path"; // Nous pouvons également créer un lien direct vers un numéro de ligne, si nous l'avons. Github // supporte ceci en ajoutant #L à la fin de l'URL: if ($ line! == null) $ url. = "#L $ line";  $ frame-> addComment ($ url, "github-linker");  return Handler :: DONE; ?>

Ça y est, dans la mesure où notre gestionnaire va. Mettez cette classe quelque part dans votre projet, et tout ce qui reste à faire est d'activer et de l'essayer:

 pushHandler (new LaravelGithubLinkHandler ()); //…?>

Avec seulement quelques lignes de code, nous avons ajouté une couche supplémentaire de fonctionnalités (éventuellement inutiles, mais bon, c'est un exemple) à nos pages d'erreur. Voici quelques idées supplémentaires, si vous êtes à la recherche d'un défi:

  • Compilez votre gestionnaire d'erreurs personnalisé en tant que fournisseur de services Laravel.
  • Utilisez-vous Git pour gérer votre projet? Construire un gestionnaire personnalisé qui s’accroche à blâme pour déterminer qui était la dernière personne à toucher ce fichier qui lançait une exception (et crier dessus) était directement à partir de la page d'erreur.
  • Si vous vous sentez courageux, utilisez le PHP-Parser de nikic pour analyser le code compliqué et suggérer des solutions (je vous promets que ce n'est pas aussi compliqué qu'il n'y paraît)..

Dernières pensées

J'espère que ce petit guide vous a aidé à comprendre le type de possibilités offertes par cette bibliothèque dans vos projets quotidiens. Pour plus d'informations, reportez-vous à la documentation complète de l'API..

Whoops est agnostique, léger et, je pense, assez puissant dans sa simplicité et se concentre sur la combinaison et la correspondance de petits outils. Il est également open-source et ouvert aux suggestions et améliorations. Si vous souhaitez contribuer ou signaler un bogue, allez au dépôt officiel.!