Whoops! PHP Errors voor Cool Kids

Whoops is een kleine bibliotheek, beschikbaar als een Composer-pakket, waarmee je fouten en uitzonderingen in al je PHP-projecten kunt afhandelen.

Out of the box, krijg je een gestroomlijnde, intuïtieve en informatieve foutpagina elke keer dat er iets in je applicatie wordt opgepakt. Sterker nog, onder al dat is een zeer eenvoudige, maar flexibele toolset voor het omgaan met fouten op een manier die logisch is voor wat je ook aan het doen bent.

De belangrijkste kenmerken van de bibliotheek zijn:

  • Gedetailleerde en intuïtieve pagina voor fouten en uitzonderingen
  • Codeweergave voor alle frames
  • Focus op fout- / uitzonderinganalyse door het gebruik van aangepaste, eenvoudige middle-ware / handlers
  • Ondersteuning voor JSON- en AJAX-verzoeken
  • Inbegrepen providers voor Silex- en Zend-projecten via de gebundelde providers en opgenomen als onderdeel van de Laravel 4-kern
  • Schone, compacte en geteste codebasis, zonder extra afhankelijkheden

Whoops bereikt dit via een systeem van gestapelde afhandelaars. Je vertelt Whoops welke handlers je wilt gebruiken (je kunt kiezen uit de inbegrepen handlers of je eigen maken), en als er iets gebeurt, worden alle handlers gegeven, in volgorde, een kans om iets te doen - dit kan alles zijn van het analyseren van de fout (Whoops maakt het gemakkelijker om zinvolle informatie uit een fout of uitzondering te extraheren), om nuttige foutschermen weer te geven (zoals de ingebouwde PrettyPageHandler, wat je de coole pagina geeft die je hierboven ziet).

Laten we het eens proberen, eerst door naar de basisprincipes te kijken en vervolgens door onze eigen handler te bouwen met Whoops en het Laravel-framework. Voor deze korte handleiding ga ik ervan uit dat je redelijk comfortabel bent met PHP en dat je hebt gehoord van Composer. Als dit niet het geval is, lees het hier op Nettuts+.


Whoops installeren

Maak een map voor uw project, verander erin, maak een composer.json bestand met de Whoops-vereiste en installeer het. Whoops (vanaf versie 1.0.5) heeft geen afhankelijkheden, dus dit duurt maar een seconde.

 $ cd / path / to / your / project $ composer vereist filp / whoops 1. * $ composer install

Whoops gebruiken: de basis

Om die gestroomlijnde foutpagina in actie te zien, laten we Whoops instellen en ervoor zorgen dat iets breekt door een uitzondering in onze code te gooien. Maak een bestand binnen de map van uw project; voor deze gids, laten we zeggen dat het is genoemd, index.php.

 $ cd / path / to / your / project $ uw-favoriet-editor index.php

Omdat we Whoops hebben geïnstalleerd met Composer en het voldoet aan PSR-0, hoeven we alleen de autoloader van Composer te gebruiken en zijn we klaar om de bibliotheek binnen onze eigen code te gebruiken!

 pushHandler (nieuwe Whoops \ Handler \ PrettyPageHandler ()); // Stel Whoops in als standaardfout- en uitzonderingshandler gebruikt door PHP: $ whoops-> register (); gooi nieuwe RuntimeException ("Oopsie!"); ?>

Als je al een webserver hebt, ga je gang en open je het bestand dat je zojuist hebt gemaakt. Vergeet niet: als u PHP 5.4 gebruikt, kunt u gebruikmaken van de ingebouwde ontwikkelserver, zoals:

 $ cd / pad / naar / uw / project $ php -S localhost: 8080

Dit is wat je krijgt:

Best leuk, toch? Handlers kunnen zelf opties blootleggen om hun gedrag aan te passen of te vergroten. U kunt bijvoorbeeld onder andere de titel van de standaardfoutpagina instellen en zelfs extra informatie invoegen:

 setPageTitle ("It's broken!"); // Stel de titel van de pagina $ errorPage-> setEditor ("subliem") in; // Stel de editor in voor de "Open" link $ faultPage-> addDataTable ("Extra Info", array ("stuff" => 123, "foo" => "bar", "useful-id" => "flauwekul ")); $ Whoops-> pushHandler ($ errorPage); $ Whoops-> registreren (); gooi nieuwe RuntimeException ("Oopsie!"); ?>

Omdat dit eenvoudigweg een gewone Whoops-handler is, kunnen we ook mixen en matchen met andere handlers om meer dynamische resultaten te bereiken. Laten we ons voorstellen dat u werkt aan een AJAX + JSON-gestuurde website. Als je applicatie op de een of andere manier zou falen, zou je op het moment een hoop vervelende HTML in de pijplijn krijgen, toen je JSON verwachtte. Geen probleem:

 pushHandler (nieuwe Whoops \ Handler \ PrettyPageHandler ()); $ whoops-> pushHandler (nieuwe Whoops \ Handler \ JsonResponseHandler ()); $ Whoops-> registreren (); gooi nieuwe RuntimeException ("Oopsie!");

Dat is het. Als er iets mislukt tijdens een AJAX-aanvraag, antwoordt Whoops met een JSON-reactie waarin de fout wordt vermeld. Als dit GEEN AJAX-verzoek is, blijft de normale foutpagina zichtbaar. Als er een fout optreedt, filtert Whoops alle geregistreerde handlers (beginnend bij de laatste handler die moet worden geregistreerd) en geeft ze een kans om het verzoek te analyseren, te wijzigen en op het verzoek te reageren.

Nu je een algemeen idee hebt van hoe Whoops werkt, kunnen we onze eigen handler bouwen met Whoops en het Laravel 4-framework.


Whoops en Laravel 4

Laravel 4 bundelt Whoops als core exception-handler, standaard ingeschakeld in ontwikkelmodus, inclusief een aangepast kleurenschema van Dayle Rees:

Als je Laravel nog niet hebt geïnstalleerd, ga dan verder en volg de installatiestappen. Laravel wordt uitgebreid behandeld op Nettuts + en Tuts + Premium, dus je zult hier veel training vinden, als je verder wilt graven.

Voor de volgende stappen, neem ik aan dat je enigszins op je gemak bent met de basisprincipes van Laravel 4. Maar zelfs als je dat niet bent, zou het nog steeds gemakkelijk te volgen moeten zijn.

Als u zich in de ontwikkelingsmodus (debug) bevindt, is Whoops beschikbaar via de IoC-container als whoops, en vooraf ingesteld met een van de twee handlers: PrettyPageHandler of JsonResponseHandler, zoals whoops.handler (dezelfde twee waar we het zojuist over hadden). Beide handlers stellen bruikbare aanvullende methoden bloot, zoals je hierboven hebt gezien met de PrettyPageHandler. Door toegang te krijgen tot deze services, kunnen we beginnen met het aanpassen van onze Whoops-ervaring binnen het kader.

Voor de eenvoud, in jouw app / routes.php bestand, laten we inhaken op de Whoops-service en een aangepaste paginatitel instellen voor onze foutpagina's:

 setPageTitle ("Houston, we hebben een probleem!"); // Stel de "open:" link voor bestanden in naar onze editor naar keuze: $ whoopsDisplayHandler-> setEditor ("subliem");  Route :: get ('/', function () // Dwing de uitvoering om te mislukken door een uitzondering te geven: gooi nieuwe RuntimeException ("Oopsie!");); ?>

Tip: Whoops ondersteunt standaard een paar editors en biedt u de mogelijkheid ondersteuning voor uzelf te implementeren zoals u dat wilt. Lees hier meer over.

Als u nu toegang krijgt tot uw Laravel-toepassing, wordt u begroet met een foutmelding met uw aangepaste paginatitel. Als u op het bestandspad boven het codevak klikt, moet het bestand waarnaar wordt verwezen, rechtstreeks in uw editor of IDE naar keuze worden geopend. Hoe cool is dat? Omdat we de handler kunnen bereiken die al door de Laravel-kern is ingesteld, kunnen we ook de andere functies gebruiken die we hierboven hebben geleerd. We kunnen bijvoorbeeld aangepaste tabellen toevoegen (met PrettyPageHandler :: addDataTable) met nuttige informatie over onze applicatie.

Laten we een ander voorbeeld proberen. Dit is onze eerste poging om onze eigen aangepaste handler te schrijven. We willen alle stackframes ontvangen voor een uitzondering en alles verwijderen dat geen deel uitmaakt van onze applicatiecode. Klinkt eenvoudig genoeg, toch??

 pushHandler (function ($ exception, $ exceptionInspector, $ runInstance) // Verkrijg de verzameling stackframes voor de huidige uitzondering: $ frames = $ exceptionInspector-> getFrames (); // Filter bestaande frames zodat we alleen de frames behouden de app / map $ frames-> filter (functie ($ frame) $ filePath = $ frame-> getFile (); // Vergelijk elk bestandspad met / app / ... return preg_match ("/ \ / app \ /.+ / i ", $ filePath);); return Handler :: DONE;);  Route :: get ('/', function () // Dwing de uitvoering om te mislukken door een uitzondering te geven: gooi nieuwe RuntimeException ("Oopsie!");); ?>

Tip: Je hoeft niet echt terug te keren Handler :: DONE - dit dient slechts een semantisch doel. Als je wilt dat Whoops stopt met het uitvoeren van extra handlers na jouw account, schrijf dan retour handler :: LAST_HANDLER. Als je wilt dat Whoops de uitvoering van het script afsluit na je handler, return Handler :: QUIT.

Je kunt zien dat het opmerkelijk beknopt is. Whoops \ Run's pushHandler methode accepteert een afsluiting die maximaal drie argumenten ontvangt: het uitzonderingsobject, een uitzonderingsinspecteur, die enkele gebruiksmethoden blootstelt aan, u raadt het al, inspecteert uitzonderingen en de uitzondering Whoops \ Run instantie die de uitzondering heeft vastgelegd. Via deze handler gebruiken we de uitzonderingsinspecteur om de stapelframes te extraheren, allemaal binnen een nette FrameCollection voorwerp:

 getFrames (); // # => Whoops \ Exception \ FrameCollection; tellen ($ frames); # => int foreach ($ frames als $ frame) get_class ($ frame); // # => Whoops \ Exception \ Frame print $ frame-> getFile (). ":". $ frame-> getLine (). "\ N"; # => "/path/to/file.php:123"?>

Tip: Whoops converteert intern sluitingen naar een speciale handler: Whoops \ Handler \ CallbackHandler.

U kunt de inhoud van deze klasse tellen, herhalen, in kaart brengen en filteren, met het interessante maar belangrijke aspect dat de kaart en filterbewerkingen het object op zijn plaats muteren. Dit betekent dat beide bewerkingen de oorspronkelijke instantie rechtstreeks wijzigen in plaats van een nieuwe verzameling te maken. Hoe is dit belangrijk? Het betekent dat handlers gemakkelijker wijzigingen kunnen uitvoeren die zich naar beneden uitbreiden naar alle andere handlers in de stapel. Dit is precies wat we deden met onze eenvoudige handler hierboven. Als u het script nu opnieuw uitvoert, ziet u dat we een kortere lijst met stackframes krijgen, alleen met betrekking tot de code die in onze applicatiemap staat.

Wat betreft het frame-object zelf (Whoops \ Uitzondering \ Frame), stelt het een reeks methoden bloot voor het verzamelen van informatie over de frame-inhoud (het bestandspad, het regelnummer, de methode- of functieaanroep, de klassennaam enz.) en methoden waarmee u opmerkingen aan afzonderlijke stapelframes kunt koppelen. Een framereactie is een handige functie in Whoops waarmee handlers aanvullende informatie kunnen bieden die ze van een uitzondering verzamelen door aantekeningen rechtstreeks aan afzonderlijke frames in de stapel te koppelen. Handlers zoals de PrettyPageHandler, kan deze opmerkingen bijvoorbeeld verzamelen en samen met het bestandspad en het regelnummer van het frame weergeven.

 pushHandler (functie ($ exception, $ exceptionInspector, $ runInstance) foreach ($ exceptionInspector-> getFrames () als $ i => $ frame) $ frame-> addComment ("Dit is framenummer $ i");  return Handler :: DONE;); ?>

Frame-opmerkingen kunnen ook een seconde ontvangen strekking argument. Als u meerdere aangepaste handlers hebt, kunt u bijvoorbeeld framereacties filteren op dit argument om alleen de informatie te verzamelen die belangrijk voor u is.

 getFrames (); foreach ($ frames as $ frame) // Was dit frame binnen een controllerklasse? (eindigt in Controller) $ className = $ frame-> getClass (); if (substr ($ className, -10) == "Controller") $ frame-> addComment ("Dit frame bevindt zich in een controller: $ className", "controller-error");  // Later, in een andere handler, krijgt u alle opmerkingen binnen de scope 'controller-errors': $ controllerErrors = $ frame-> getComments ("controller-errors"); // # => array?>

Ook van belang, de PrettyPageHandler natuurlijk HTML-ontsnapt aan de frame-opmerkingen voordat ze worden weergegeven, maar zal op intelligente wijze URI's in de body van de commentator vastleggen en ze converteren naar klikbare ankerelementen. Wilt u frames koppelen aan documentatie of GitHub-repositories? Het is gemakkelijk genoeg; laten we onze eigen handler class creëren voor dit voorbeeld.

Tip: Door je eigen klasse te gebruiken in plaats van een afsluiting, heb je wat extra controle over je handler - om nog maar te zwijgen van het gemakkelijker maken om met geautomatiseerde tests te dekken. Uw aangepaste handlerklassen moeten de Whoops \ Handler \ HandlerInterface interface, maar u kunt in plaats daarvan eenvoudigweg het Whoops \ Handler \ Handler klasse, en implementeer de vermiste handvat methode, zoals getoond in het onderstaande voorbeeld.

 getInspector () -> getFrames (); foreach ($ frames als $ frame) $ file = $ frame-> getFile (); $ line = $ frame-> getLine (); // Sommige frames hebben mogelijk geen bestandspad, bijvoorbeeld als het binnen // a Closure is gekomen, dus we moeten dat controleren: als (! $ -Bestand) wordt voortgezet; // Controleer of het bestandspad voor dit frame zich binnen de directory laravel / framework // binnen de leverancier / directory van Composer bevond en gebruik een regex-capture // om alleen de gewenste delen te extraheren: if (preg_match ("/ \ / vendor \ / laravel \ / framework \ / (. +) $ / ", $ file, $ matches)) $ path = $ matches [1]; // Eerste overeenkomst is volledig pad, ten tweede is onze capture $ url = "$ this-> repoBase / $ path"; // We kunnen ook rechtstreeks naar een regelnummer linken, als we het hebben. Github // ondersteunt dit door #L toe te voegen aan het einde van de URL: if ($ line! == null) $ url. = "#L $ line";  $ frame-> addComment ($ url, "github-linker");  return Handler :: DONE; ?>

Dat is alles, voor zover onze handler gaat. Zet die klasse ergens in uw project en alles wat u hoeft te doen, is het inschakelen en uitproberen:

 pushHandler (nieuwe LaravelGithubLinkHandler ()); // ...?>

Met slechts een handvol regels code hebben we een extra laag (mogelijk nutteloze, maar toch een voorbeeld) functionaliteit toegevoegd aan onze foutpagina's. Hier zijn een paar extra ideeën, als u op zoek bent naar een uitdaging:

  • Verpak uw aangepaste foutafhandelaar als een Laravel-serviceprovider.
  • Gebruikt u Git om uw project te beheren? Bouw een aangepaste handler die inhaakt git-schuld om te bepalen wie de laatste persoon is die het bestand aanraakt dat een uitzondering blijft maken (en tegen hen schreeuwt), rechtstreeks van de foutpagina.
  • Als je moedig bent, gebruik dan PHP-Parser van nikic om de lastige code te analyseren en suggesties voor fixes te geven (ik beloof dat het niet zo ingewikkeld is als het klinkt).

Laatste gedachten

Ik hoop dat deze korte handleiding u heeft geholpen inzicht te krijgen in de mogelijkheden die deze bibliotheek biedt voor uw dagelijkse projecten. Raadpleeg de volledige API-documentatie voor meer informatie.

Whoops is raamwerk-agnostisch, lichtgewicht en, geloof ik, behoorlijk krachtig in zijn eenvoud en focus op mix-en-matching kleine tools. Het is ook open-source en open voor suggesties en verbeteringen. Als je een bug wilt bijdragen of melden, ga dan naar de officiële repository!