Oj då! PHP Fel för Cool Kids

Whoops är ett litet bibliotek, tillgängligt som kompositörspaket, som hjälper dig att hantera fel och undantag i dina PHP-projekt.

Utanför lådan får du en elegant, intuitiv och informativ felsida varje gång något går upp i din ansökan. Ännu bättre, under allt det är en mycket rakt framåt men flexibel verktygssats för att hantera fel på ett sätt som är meningslöst för vad det än är som du gör.

Bibliotekets huvudfunktioner är:

  • Detaljerad och intuitiv sida för fel och undantag
  • Kodvisning för alla ramar
  • Fokusera på fel / undantagsanalys genom användandet av anpassade, enkla medelhanterare / hanterare
  • Stöd för JSON och AJAX-förfrågningar
  • Inkluderade leverantörer för Silex och Zend-projekt genom de bundna leverantörerna, och ingår som en del av Laravel 4-kärnan
  • Ren, kompakt och testad kodbas, utan extra beroenden

Whoops åstadkommer detta genom ett system med staplade handlers. Du berättar Whoops vilka hanterare du vill använda (du kan välja från den medföljande hanteraren eller göra din egen), och om något händer, ges alla hanterare, för att göra en chans att göra någonting - det kan vara allt från att analysera fel (Whoops gör det lättare att extrahera meningsfull information från ett fel eller undantag), för att visa användbara felskärmar (som den inbyggda PrettyPageHandler, vilket ger dig den coola sidan som bilden ovan).

Låt oss försöka först, genom att titta på grunderna, och sedan genom att gå på att bygga vår egen handlare med Whoops och Laravel-ramverket. För den här korta guiden antar jag att du är måttligt bekväm med PHP, och att du har hört talas om kompositören. Om så inte är fallet läs det här på Nettuts+.


Installera Whoops

Skapa en katalog för ditt projekt, byt till det, skapa en composer.json filen med Whoops-kravet och installera det. Whoops (från version 1.0.5) har inga beroenden, så det tar bara en sekund.

 $ cd / path / to / your / project $ composer kräver filp / whoops 1. * $ composer install

Använda Whoops: Grunderna

För att se den snygga felsidan i åtgärd, låt oss setup Whoops och se till att något bryts genom att kasta ett undantag i vår kod. Skapa en fil i ditt projekts katalog för den här guiden, låt oss säga att det heter, index.php.

 $ cd / path / to / your / project $ din-favorit-editor index.php

Eftersom vi installerade Whoops with Composer, och det är PSR-0-kompatibelt, är allt vi behöver göra krävs Composer autoloader och vi är redo att börja använda biblioteket i vår egen kod!

 pushHandler (nya Whoops \ Handler \ PrettyPageHandler ()); // Ange vem som standardfel och undantagshanterare som används av PHP: $ whoops-> register (); kasta ny RuntimeException ("Oopsie!"); ?>

Om du redan har en webbserver köra, fortsätt och öppna filen som du just skapat. Glöm inte: Om du använder PHP 5.4 kan du utnyttja den inbyggda utvecklingsservern, som så:

 $ cd / sökväg / till / ditt / projekt $ php -S localhost: 8080

Så här får du:

Ganska snyggt, eller hur? Handlers, själva, kan avslöja alternativ för att ändra eller öka deras beteende. Till exempel kan du bland annat ställa in titeln på standardfelsidan och till och med lägga till extra information:

 setPageTitle ("Det är trasigt!"); // Ange sidans titel $ errorPage-> setEditor ("sublime"); // Ange redigeraren som används för länken "Öppna" $ errorPage-> addDataTable ("Extra Info", array ("stuff" => 123, "foo" => "bar", "useful-id" => "baloney ")); $ Whoops-> pushHandler ($ errorPage); $ Whoops-> registrera (); kasta ny RuntimeException ("Oopsie!"); ?>

Eftersom det här helt enkelt är en vanlig Whoops-hanterare kan vi mixa och matcha andra handlare för att uppnå mer dynamiska resultat. Låt oss föreställa er att du arbetar på en AJAX + JSON-driven webbplats. Just nu, om din ansökan skulle misslyckas på något sätt skulle du få en massa otäck HTML som kommer ner i röret när du väntade JSON. Ingen stor grej:

 pushHandler (nya Whoops \ Handler \ PrettyPageHandler ()); $ whoops-> pushHandler (new Whoops \ Handler \ JsonResponseHandler ()); $ Whoops-> registrera (); kasta ny RuntimeException ("Oopsie!");

Det är allt. Om något misslyckas under en AJAX-förfrågan kommer Whoops att svara med ett JSON-svar som anger felet. Om det inte är en AJAX-förfrågan fortsätter du att se den vanliga felsidan. Om ett fel uppstår, kommer Whoops att filtrera genom var och en av de registrerade hanterarna (från den sista handlaren som ska registreras) och ge dem en chans att analysera, modifiera och svara på begäran.

Nu när du har en allmän uppfattning om hur Whoops fungerar, låt oss gå på att bygga vår egen handlare med Whoops och Laravel 4-ramarna.


Whoops och Laravel 4

Laravel 4 buntar Whoops som en grundläggande undantagshanterare, som standard aktiverad i utvecklingsläge, inklusive ett anpassat färgschema av Dayle Rees:

Om du inte har installerat Laravel ännu, gå vidare och följ installationsstegen. Laravel är omfattat omfattande på Nettuts + och Tuts + Premium, så du hittar mycket träning här om du vill gräva dig längre.

För nästa steg antar jag att du är lite bekväm med grunderna i Laravel 4. Men även om du inte är det, borde det fortfarande vara lätt att följa.

Om du befinner dig i utveckling (debug) -läge, är Whoops tillgänglig via IoC-behållaren som Oj då, och förinställd med en av två hanterare: PrettyPageHandler eller JsonResponseHandler, som whoops.handler (samma två vi pratade bara om). Båda dessa hanterare avslöjar användbara ytterligare metoder, som du har sett ovan med PrettyPageHandler. Genom att komma åt dessa tjänster kan vi börja anpassa vår Whoops-erfarenhet inom ramen.

För enkelhetens skull, i din app / routes.php fil, låt oss koppla in i Whoops-tjänsten och ange en anpassad sidtitel för våra fel sidor:

 setPageTitle ("Houston, vi har ett problem!"); // Ange länken "öppna:" för filer till vår redaktör: $ whoopsDisplayHandler-> setEditor ("sublime");  Rutt :: få ('/', funktion () // Kör utförandet att misslyckas genom att kasta ett undantag: kasta ny RuntimeException ("Oopsie!");); ?>

Tips: Whoops stöder några redaktörer som standard, och låter dig implementera stöd för din egen som du vill. Läs mer om det här.

Om du nu får tillgång till din Laravel-ansökan, kommer du att hälsas med ett felmeddelande med din anpassade sidtitel. Om du klickar på filvägen ovanför kodrutan bör den öppna filen refereras direkt i din redigerare eller IDE. Hur coolt är inte det? Eftersom vi kan nå den hanterare som redan är inställd av Laravel-kärnan kan vi också använda de andra funktionerna vi har lärt oss ovan. Till exempel kan vi lägga till anpassade tabeller (med PrettyPageHandler :: addDataTable) med användbar information om vår ansökan.

Låt oss gå till ett annat exempel. Detta är vårt första försök att skriva vår egen anpassade hanterare. Vi vill få alla stackramarna för ett undantag och ta bort allt som inte ingår i vår programkod. Låter enkelt nog, höger?

 pushHandler (funktion ($ undantag, $ exceptionInspector, $ runInstance) // Hämta samlingen av stapelramar för det nuvarande undantaget: $ frames = $ exceptionInspector-> getFrames (); // Filtrera befintliga ramar så att vi bara behåller dem inuti appen / mappen $ frames-> filter (funktion ($ frame) $ filePath = $ frame-> getFile (); // Matcha någon filväg som innehåller / app / ... returnera preg_match ("/ \ / app \ /.+ / i ", $ filePath);); returnera Handler :: DONE;);  Rutt :: få ('/', funktion () // Kör utförandet för att misslyckas genom att kasta ett undantag: kasta ny RuntimeException ("Oopsie!");); ?>

Tips: Du behöver inte faktiskt återvända Handler :: DONE - Detta tjänar bara en semantisk syfte. Om du vill att Whoops ska sluta köra några extrahanterare efter din, skriv Retur Handler :: LAST_HANDLER. Om du vill ha Whoops för att avsluta exekveringen av skriptet efter din hanterare, Return Handler :: QUIT.

Du kan se att det är anmärkningsvärt koncist. Whoops \ Run's pushHandler Metoden accepterar en nedläggning som tar emot upp till tre argument: Undantagsobjektet, en undantagsinspektör, som avslöjar vissa användningsmetoder till, du gissade det, inspekterar undantag och Whoops \ Run exempel som fångade undantaget. Genom denna hanterare använder vi undantagsinspektören för att extrahera stapelramarna, allt inom en snygg FrameCollection objekt:

 getFrames (); // # => Whoops \ Undantag \ FrameCollection; räkna ($ ramar); # => int foreach ($ frames as $ frame) get_class ($ frame); // # => Whoops \ Undantag \ Frame print $ frame-> getFile (). ":". $ frame-> getLine (). "\ N"; # => "/path/to/file.php:123"?>

Tips: Whoops konverterar internt tillslutningar till en speciell handlare: Hoppsan \ Handler \ CallbackHandler.

Du kan räkna, iterera, kartlägga och filtrera innehållet i den här klassen, med den intressanta men viktiga aspekten att kart- och filteroperationerna muterar föremålet på plats. Det innebär att båda dessa åtgärder ändrar den ursprungliga instansen direkt istället för att skapa en ny samling. Hur är det här viktigt? Det betyder att hanterare lättare kan utföra ändringar som sprider sig nedåt till alla andra hanterare i stapeln. Detta är precis vad vi gjorde med vår enkla handlare ovan. Om du nu kör skriptet igen ser du att vi får en kortare lista över stapelramar, endast om koden som bor i vår programkatalog.

Vad gäller ramobjektet, själv (Whoops \ Undantag \ Frame), exponerar den en uppsättning metoder för att samla information om raminnehållet (filvägen, radnummer, metoden eller funktionsanropet, klassnamnet etc) och metoder som låter dig bifoga kommentarer till enskilda stapelramar. En ramkommentare är en användbar funktion i Whoops som tillåter hanterare att tillhandahålla ytterligare information som de samlar från ett undantag genom att bifoga anteckningar direkt till enskilda ramar i stapeln. Hanterare som PrettyPageHandler, kan till exempel samla dessa kommentarer och visa dem tillsammans med ramens filväg och linjenummer.

 pushhandler (funktion ($ undantag, $ exceptionInspector, $ runInstance) foreach ($ exceptionInspector-> getFrames () som $ i => $ frame) $ frame-> addComment ("Detta är ramnummer $ i");  Return Handler :: DONE;); ?>

Ramkommentarer kan också få en sekund omfattning argument. Om du har flera anpassade hanterare kan du till exempel filtrera ramkommentarer med detta argument för att bara samla in informationen du bryr dig om.

 getFrames (); foreach ($ frames as $ frame) // Var denna ram inom en controller klass? (slutar i Controller) $ className = $ frame-> getClass (); if (substr ($ className, -10) == "Controller") $ frame-> addComment ("Denna ram är inuti en controller: $ className", "controller-error");  // Senare, i en annan hanterare, få alla kommentarer inom ramen för "controller-errors": $ controllerErrors = $ frame-> getComments ("controller-errors"); // # => array?>

Också av intresse är PrettyPageHandler Naturligt HTML-rymmer ramkommentaren innan de visas, men kommer intelligent att fånga URI i kommentarens kropp och konvertera dem till klickbara ankarelement. Vill du länka bilder till dokumentation eller till GitHub-repositorier? Det är lätt nog; låt oss skapa vår egen hanterarklass för detta exempel.

Tips: Att använda din egen klass i stället för stängning ger dig lite extra kontroll över din hanterare - för att inte göra det enklare att täcka med automatiska test. Dina anpassade hanterarklasser måste implementera Hoppsan \ Handler \ HandlerInterface gränssnitt, men du kan istället bara förlänga Hoppsan \ Handler \ Handler klass och implementera den saknade hantera metod, som visas i exemplet nedan.

 getInspector () -> getFrames (); foreach ($ ramar som $ ram) $ file = $ frame-> getFile (); $ line = $ frame-> getLine (); // Några ramar får inte ha en filväg, till exempel om den är ocurred inom // a Closure, så vi måste checka för det: om (! $ File) fortsätt; // Kontrollera om filvägen för den här ramen fanns inom mappen Laravel / Framework //, inuti Composer-leverantören / katalogen och använd en regex capture // för att extrahera bara de delar vi vill ha: om (preg_match ("/ \ / leverantör \ / laravel \ / framework \ / (. +) $ / ", $ fil, $ matchningar)) $ path = $ matchningar [1]; // Första matchen är hela sökvägen, den andra är vår fångst $ url = "$ this-> repoBase / $ path"; // Vi kan också länka direkt till ett radnummer, om vi har det. Github // stöder detta genom att lägga till #L till slutet av webbadressen: om ($ line! == null) $ url. = "#L $ line";  $ frame-> addComment ($ url, "github-linker");  Return Handler :: DONE; ?>

Det är så mycket som vår handlare går. Sätt den klassen någonstans i ditt projekt, och allt som är kvar att göra är att aktivera och prova det:

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

Med bara en handfull kodrader har vi lagt till ett extra lager av (eventuellt värdelös, men hej, det är ett exempel) funktionalitet till våra fel sidor. Här är några extra idéer, om du letar efter en utmaning:

  • Paketera din anpassade felhanterare som Laravel-tjänsteleverantör.
  • Använder du Git för att hantera ditt projekt? Bygg en anpassad hanterare som krokar in git-skulden för att bestämma vem den sista personen som berör den filen som håller på att kasta ett undantag (och skrika på dem) var direkt från felsidan.
  • Om du känner dig modig, använd nikics PHP-Parser för att analysera den besvärliga koden och ge förslag på korrigeringar (jag lovar att det inte är så komplicerat som det låter).

Slutgiltiga tankar

Jag hoppas att den här korta guiden har hjälpt dig att förstå vilka möjligheter biblioteket möjliggör i dina dagliga projekt. Mer information finns i fullständig API-dokumentation.

Whoops är ram-agnostisk, lätt och, tror jag, ganska kraftfull i sin enkelhet och fokuserar på mix-och-matchande små verktyg. Den är också öppen källkod och öppen för förslag och förbättringar. Om du vill bidra eller rapportera en bugg, gå till det officiella förvaret!