Hopa! Erori PHP pentru copiii răi

Whoops este o bibliotecă mică, disponibilă ca un pachet Composer, care vă ajută să gestionați erorile și excepțiile din cadrul proiectelor PHP.

Din cutie, veți obține o pagină de eroare elegantă, intuitivă și informativă de fiecare dată când în aplicația dvs. apare ceva pantaloni. Chiar mai bine, sub tot ceea ce este un set de instrumente foarte direct, dar flexibil, pentru a face față erorilor într-un mod care are sens pentru orice este ceea ce faci.

Principalele caracteristici ale bibliotecii sunt:

  • Pagina detaliată și intuitivă pentru erori și excepții
  • Vizualizare cod pentru toate cadrele
  • Concentrați-vă pe analiza erorilor / excepțiilor prin utilizarea unor comenzi personalizate / simple de tip middleware / handlers
  • Sprijin pentru cererile JSON și AJAX
  • Furnizori incluși pentru proiectele Silex și Zend prin intermediul furnizorilor grupați și inclusi ca parte a platformei Laravel 4
  • Curățată, compactă și testată bază de cod, fără dependințe suplimentare

Oamenii realizează acest lucru printr-un sistem de manipulatori stivuiți. Spuneți Oare ce manipulatori doriți să utilizați (puteți alege din manageri inclusi sau puteți crea propriul dvs.) și, dacă se întâmplă ceva, toți manipulanții sunt dat, în ordine, o șansă de a face ceva - aceasta poate fi orice, de la analizarea eroare (Oamenii simplifică extragerea informațiilor semnificative dintr-o eroare sau o excepție), afișarea unor ecrane utile de eroare (cum ar fi built-in PrettyPageHandler, care vă oferă pagina de interesantă imagine de mai sus).

Să încercăm, mai întâi, să ne uităm la elementele de bază și apoi să ne construim propriul handler cu Whoops și cadrul Laravel. Pentru acest scurt ghid, presupun că sunteți destul de confortabil cu PHP și că ați auzit de compozitor. Dacă nu este așa, citiți-o aici la Nettuts+.


Instalarea Oamenilor

Creați un director pentru proiectul dvs., schimbați-l în el, creați un composer.json fișier cu cerința Whoops și instalați-l. Oamenii (de la versiunea 1.0.5) nu au dependențe, deci va dura doar o secundă.

 $ cd / path / to / your / project $ compozitorul necesită filp / whoops 1. * $ install compose

Folosind Hopa: Elementele de bază

Pentru a vedea acea pagină de eroare elegantă în acțiune, hai să configuram Whoops și să ne asigurăm că ceva se rupe aruncând o excepție în cadrul codului nostru. Creați un fișier în directorul proiectului dvs. pentru acest ghid, să spunem că se numește, index.php.

 $ cd / path / to / your / proiect $ dvs.-preferat-editor index.php

Deoarece am instalat Whoops with Composer și este compatibil cu PSR-0, tot ce trebuie să facem este să solicităm autoloaderul Compozitor și suntem gata să începem să folosim biblioteca în propriul cod!

 pushHandler (noul Whoops \ Handler \ PrettyPageHandler ()); // Setați Whoops ca eroare implicită și procedura de tratare a excepțiilor utilizate de PHP: $ whoops-> register (); arunca noul RuntimeException ("Oopsie!"); ?>

Dacă aveți deja un server web rulat, continuați și accesați fișierul pe care tocmai l-ați creat. Nu uitați: dacă utilizați PHP 5.4, puteți utiliza serverul de dezvoltare încorporat, cum ar fi:

 $ cd / path / to / your / project / php -S localhost: 8080

Aceasta este ceea ce veți obține:

Destul de curat, nu? Handlerele, ele însele, pot expune opțiuni pentru a le modifica sau spori comportamentul. De exemplu, printre altele, puteți seta titlul paginii de eroare implicită și chiar puteți introduce informații suplimentare:

 setPageTitle ("Este rupt!"); // Setați titlul paginii $ errorPage-> setEditor ("sublime"); // Setați editorul folosit pentru link-ul "Deschis" $ errorPage-> addDataTable ("Extra Info", array ("stuff" => 123, "foo" => "bar" ")); $ Whoops-> pushHandler ($ errorPage); $ Whoops-> registru (); arunca noul RuntimeException ("Oopsie!"); ?>

De asemenea, deoarece acest lucru este pur și simplu un manipulator obișnuit Whoops, putem amesteca și se potrivi cu alți manipulatori pentru a obține rezultate mai dinamice. Să ne imaginăm că lucrați la un site Web condus de AJAX + JSON. Chiar acum, dacă aplicația dvs. va eșua într-un fel, veți obține o grămadă de hărțuit HTML care coboară pe conductă, când vă așteptați la JSON. Nu e mare lucru:

 pushHandler (noul Whoops \ Handler \ PrettyPageHandler ()); $ whoops-> pushHandler (noul Whoops \ Handler \ JsonResponseHandler ()); $ Whoops-> registru (); arunca noul RuntimeException ("Oopsie!");

Asta e. Acum, dacă ceva nu reușește în timpul unei solicitări AJAX, Whoops va răspunde cu un răspuns JSON care detaliază eroarea. Dacă nu este o solicitare AJAX, veți continua să vedeți pagina de eroare regulată. Dacă apare o eroare, Whoops va filtrează fiecare dintre persoanele care au accesat înregistrarea (începând cu ultimul handler care urmează să fie înregistrat) și le va da o șansă de a analiza, modifica și răspunde solicitării.

Acum că aveți o idee generală despre modul în care funcționează Whoops, hai să ne construim propriul nostru handler cu Whoops și Laravel 4 framework.


Oamenii și Laravel 4

Laravel 4 bundles Whoops ca un handler de excepție de bază, activat implicit în modul de dezvoltare, inclusiv o schemă de culoare personalizată de Dayle Rees:

Dacă nu ați instalat încă Laravel, continuați și urmați pașii de instalare. Laravel este acoperit extensiv pe Nettuts + și Tuts + Premium, deci veți găsi o mulțime de antrenamente aici dacă doriți să vă grăbiți.

Pentru pașii următori, presupun că sunteți oarecum confortabil cu elementele de bază ale Laravel 4. Cu toate acestea, chiar dacă nu sunteți, ar trebui să fie ușor de urmat.

Dacă sunteți în modul de dezvoltare (depanare), Whoops este disponibil prin containerul IoC ca Hopa, și pre-setat cu unul din cei doi manipulatori: PrettyPageHandler sau JsonResponseHandler, la fel de whoops.handler (aceleași două despre care tocmai am vorbit). Ambii dintre aceștia manipulează metode suplimentare utile, după cum ați văzut mai sus cu PrettyPageHandler. Prin accesarea acestor servicii, putem începe personalizarea experienței noastre Whoops în cadrul respectiv.

Pentru simplitate, în tine app / routes.php fișier, hrănim în serviciul Whoops și setăm un titlu de pagină personalizat pentru paginile noastre de eroare:

 setPageTitle ("Houston, avem o problemă!"); // Setați link-ul "open:" pentru fișiere editorului ales: $ whoopsDisplayHandler-> setEditor ("sublime");  Traseu :: get ('/', function () // Forțarea execuției să eșueze prin aruncarea unei excepții: aruncă o nouă RuntimeException ("Oopsie!");); ?>

Bacsis: Oricine vă ajută în mod implicit pe câțiva editori și vă permite să implementați propriul suport, după cum doriți. Citiți mai multe despre el aici.

Dacă accesați acum aplicația dvs. Laravel, veți fi întâmpinat cu un mesaj de eroare cu titlul paginii personalizate. Dacă faceți clic pe calea fișierului de deasupra casetei de cod, ar trebui să deschideți fișierul referit în dreptul editorului sau IDE-ului dorit. Cat de tare e asta? De asemenea, deoarece putem ajunge la managerul deja setat de corela Laravel, putem folosi celelalte funcții pe care le-am învățat mai sus. De exemplu, putem adăuga tabele personalizate (cu PrettyPageHandler :: addDataTable) cu informații utile despre aplicația noastră.

Hai să mergem la un alt exemplu. Aceasta va fi prima noastră încercare de a scrie propriul nostru handler personalizat. Vrem să obținem toate cadrele de stivă pentru o excepție și să eliminăm orice nu face parte din codul nostru de aplicare. Suna destul de simplu, corect?

 pushHandler (funcția ($ excepție, $ exceptionInspector, $ runInstance) // Obținerea colecției de cadre de stivă pentru excepția curentă: $ frames = $ exceptionInspector-> getFrames (); // filtrarea cadrelor existente pentru a le păstra numai aplicația / directorul $ frames-> filter (funcția ($ frame) $ filePath = $ frame-> getFile (); // potriviți orice cale de fișier care conține / app / ... return preg_match ("/ \ / i ", $ filePath);); returner Handler :: DONE;);  Route :: get ('/', function () // Forțați execuția să eșueze prin aruncarea unei excepții: aruncați o nouă RuntimeException ("Oopsie!");); ?>

Bacsis: Nu trebuie să vă întoarceți Handler :: DONE - acest lucru servește doar unui scop semantic. Dacă doriți ca Whoops să înceapă să ruleze alți agenți suplimentari după dvs., scrieți return Handler :: LAST_HANDLER. Dacă doriți ca Whoops să părăsească executarea scriptului după manipularea, retur de manipulare :: QUIT.

Puteți vedea că este remarcabil de concis. Hopa \ Run„s pushHandler metoda acceptă o închidere care primește până la trei argumente: obiectul excepțional, un inspector de excepție, care expune câteva metode de utilitate la, ați ghicit-o, inspectați excepțiile și Hopa \ Run care a capturat excepția. Prin acest manipulator, vom folosi inspectorul de excepție pentru a extrage cadrele stivei, toate într-un mod îngrijit FrameCollection obiect:

 getFrames (); // # => Oameni \ Excepție \ FrameCollection; Numar de cadre ($); # => fore foreach (fraze $ ca frame $) get_class ($ frame); // # => Whoops \ Excepție \ Frame print $ frame-> getFile (). ":". $ frame-> getLine (). "\ N"; # => "/path/to/file.php:123"?>

Bacsis: Oamenii convertesc închiderea internă la un handler special: Hopa \ Handler \ CallbackHandler.

Puteți să numărați, să iterați, să cartografiați și să filtrați conținutul acestei clase, cu aspectul interesant, dar important, că operațiile hărții și filtrelor mută obiectul în loc. Aceasta înseamnă că ambele operații modifică direct instanța inițială, în loc să creeze o nouă colecție. Cum este important acest lucru? Aceasta înseamnă că utilizatorii pot efectua mai ușor modificări care se propagă în jos către toți ceilalți manipulatori din stack. Acesta este exact ceea ce am făcut cu mâna noastră simplă de mai sus. Dacă rulați din nou script-ul, veți vedea că vom obține o listă mai scurtă de cadre de stivă, numai în ceea ce privește codul care trăiește în directorul nostru de aplicații.

În ceea ce privește obiectul Frame, el însuși (Hopa \ Excepție \ Frame), acesta expune un set de metode pentru a aduna informații despre conținutul cadrului (calea fișierului, numărul liniei, apelul pentru metoda sau funcția, numele clasei etc.) și metodele care vă permit să atașați comentarii la cadrele individuale de stivă. Comentariul unui cadru este o caracteristică utilă în Whoops, care permite utilizatorilor să furnizeze informații suplimentare pe care le colectează dintr-o excepție prin atașarea de note direct la cadrele individuale din stivă. Operatorii cum ar fi PrettyPageHandler, de exemplu, pot să adune aceste comentarii și să le afișeze împreună cu calea fișierului și numărul liniei.

 ($ excepție, $ exceptionInspector, $ runInstance) foreach ($ exceptionInspector-> getFrames () ca $ i => $ frame) $ frame-> addComment ("Acesta este numărul cadrului $ i");  returner Handler :: DONE;); ?>

Comentariile cadru pot primi, de asemenea, o secundă domeniu argument. Dacă aveți mai mulți agenți personalizați, puteți, de exemplu, să filtrați comentariile de la acest argument pentru a colecta numai informațiile despre care vă interesează.

 getFrames (); foreach ($ cadre ca $ frame) // A fost acest cadru într-o clasă de controler? (se termină în Controller) $ className = $ frame-> getClass (); dacă (substr ($ className, -10) == "Controller") $ frame-> addComment ("Acest cadru este în interiorul unui controler: $ className", "controller-error");  // Mai târziu, într-un alt handler, obțineți toate comentariile în cadrul domeniului "controller-errors": $ controllerErrors = $ frame-> getComments ("eroare de controler"); // # => array?>

De asemenea, de interes, PrettyPageHandler în mod natural HTML - scapă comentariile cadrului înainte de a le afișa, dar va captura inteligent URI-urile în corpul comentariului și le va converti la elementele de ancorare clicabile. Doriți să conectați cadrele la documentație sau la depozitele GitHub? Este destul de ușor; hai să creăm clasa noastră de handler pentru acest exemplu.

Bacsis: Folosirea clasei proprii în loc de închidere vă oferă un anumit control suplimentar asupra handlerului dvs. - ca să nu mai vorbim de ușurința de acoperire cu teste automate. Clasele personalizate de handler trebuie să implementeze Hopa \ Handler \ HandlerInterface interfață, dar puteți extinde pur și simplu Hopa \ Handler \ Handler clasă, și să pună în aplicare lipsa mâner , așa cum se arată în exemplul de mai jos.

 getInspector () -> getFrames (); foreach ($ cadre ca frame de $) $ file = $ frame-> getFile (); $ linie = $ cadru-> getLine (); // Unele cadre ar putea să nu aibă o cale de fișier, de exemplu, dacă aceasta se desfășoară în // a Closure, deci trebuie să verificăm dacă: (!! File) continuă; // Verificați dacă calea fișierului pentru acest cadru se încadra în directorul laravel / framework //, în directorul Composer vendor / directory și utilizați o captură regex // pentru a extrage doar piesele dorite: if (preg_match ("/ \ vendor \ / laravel \ / frame \ / (. +) $ / ", fișier $, meciuri $)) $ path = $ matches [1]; // Primul meci este calea intreg, al doilea este capturarea $ url = "$ this-> repoBase / $ path"; // De asemenea, putem să ne conectăm direct la un număr de linie, dacă îl avem. Github // acceptă acest lucru prin adăugarea lui #L până la sfârșitul adresei URL: dacă ($ line! == null) $ url. = "#L $ line";  $ frame-> addComment ($ url, "github-linker");  retur Handler :: DONE; ?>

Asta este, în măsura în care mâna noastră merge. Puneți clasa undeva în proiectul dvs. și tot ce trebuie să faceți este să activați și să încercați:

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

Cu doar o mână de linii de cod, am adăugat un strat suplimentar de funcționalitate (eventual inutil, dar hei, este un exemplu) la paginile noastre de eroare. Iată câteva idei suplimentare dacă sunteți în căutarea unei provocări:

  • Pachetul dvs. handler de eroare personalizat ca un furnizor de servicii Laravel.
  • Utilizați Git pentru a vă gestiona proiectul? Construiți un manipulator personalizat care se încarcă git-culpabilizare pentru a determina cine ultima persoană care să atingă acel fișier care continuă să arunce o excepție (și să țipă la ele) a fost, direct de pe pagina de eroare.
  • Dacă te simți curajos, folosește PHP-Parser de la nikic pentru a analiza codul deranjant și pentru a oferi sugestii pentru remedierile (promit că nu este atât de complicat cât pare).

Gândurile finale

Sper că acest scurt ghid v-a ajutat să înțelegeți ce fel de posibilități permite această bibliotecă în proiectele de zi cu zi. Pentru mai multe informații, consultați documentația API completă.

Oamenii sunt agnostici-cadru, ușoare și, cred eu, destul de puternici în simplitatea lor și se concentrează pe uneltele mici care se amestecă și se potrivesc. Este, de asemenea, open-source și deschis la sugestii și îmbunătățiri. Dacă doriți să contribuiți sau să raportați o eroare, mergeți la depozitul oficial!

Cod