Ops! Errori PHP per Cool Kids

Whoops è una piccola libreria, disponibile come pacchetto Composer, che ti aiuta a gestire errori ed eccezioni tra i tuoi progetti PHP.

Fuori dagli schemi, ottieni una pagina di errore elegante, intuitiva e informativa ogni volta che qualcosa va a posto nella tua applicazione. Ancora meglio, sotto tutto ciò è un set di strumenti molto semplice, ma flessibile, per gestire gli errori in un modo che ha senso per qualunque cosa tu stia facendo.

Le caratteristiche principali della libreria sono:

  • Pagina dettagliata e intuitiva per errori ed eccezioni
  • Vista codice per tutti i frame
  • Concentrati sull'analisi di errori / eccezioni attraverso l'uso di middleware / gestori semplici e personalizzati
  • Supporto per richieste JSON e AJAX
  • Provider inclusi per i progetti Silex e Zend attraverso i provider in bundle e inclusi come parte del core Laravel 4
  • Base di codice pulita, compatta e testata, senza dipendenze extra

Whoops raggiunge questo attraverso un sistema di gestori impilati. Dì a Whoops quali gestori vuoi usare (puoi scegliere tra i gestori inclusi o crearne uno tuo), e se succede qualcosa, tutti i gestori sono dati, in ordine, una possibilità a qualcosa - questo può essere qualsiasi cosa, dall'analisi del errore (Whoops semplifica l'estrazione di informazioni significative da un errore o un'eccezione), la visualizzazione di schermate di errore utili (come il built-in PrettyPageHandler, che ti dà la pagina dall'aspetto interessante nella foto sopra).

Facciamo un tentativo, in primo luogo, osservando le basi, e poi provando a costruire il nostro gestore con Whoops e il framework Laravel. Per questa breve guida, presumo che tu sia moderatamente a tuo agio con PHP e che tu abbia sentito parlare di Composer. Se questo non è il caso, leggilo qui su Nettuts+.


Installare Whoops

Crea una directory per il tuo progetto, cambialo, crea un composer.json file con il requisito Whoops e installarlo. Whoops (dalla versione 1.0.5) non ha dipendenze, quindi ci vorrà solo un secondo.

 $ cd / percorso / al / tuo / progetto $ compositore richiede filp / whoops 1. * $ compositore installa

Utilizzando Whoops: The Basics

Per vedere questa pagina di errore in azione, impostiamo Whoops e assicurati che qualcosa si interrompa generando un'eccezione nel nostro codice. Creare un file all'interno della directory del progetto; per questa guida, diciamo che si chiama, index.php.

 $ cd / percorso / al / tuo / progetto $ your-favourite-editor index.php

Poiché abbiamo installato Whoops con Composer ed è compatibile con PSR-0, tutto ciò che dobbiamo fare è richiedere il caricatore automatico Composer e siamo pronti per iniziare a utilizzare la libreria con il nostro codice!

 pushHandler (new Whoops \ Handler \ PrettyPageHandler ()); // Imposta Whoops come l'errore predefinito e il gestore di eccezioni utilizzato da PHP: $ whoops-> register (); lanciare una nuova RuntimeException ("Oopsie!"); ?>

Se hai già un server web in esecuzione, vai avanti e accedi al file che hai appena creato. Non dimenticare: se stai utilizzando PHP 5.4, puoi sfruttare il server di sviluppo integrato, in questo modo:

 $ cd / percorso / al / tuo / progetto $ php -S localhost: 8080

Questo è ciò che otterrai:

Abbastanza pulito, giusto? Gli handler, da soli, possono esporre le opzioni per modificare o aumentare il loro comportamento. Ad esempio, tra le altre cose, puoi impostare il titolo della pagina di errore predefinita e persino inserire ulteriori informazioni:

 setPageTitle ("È rotto!"); // Imposta il titolo della pagina $ errorPage-> setEditor ("sublime"); // Imposta l'editor utilizzato per il collegamento "Apri" $ errorPage-> addDataTable ("Informazioni extra", array ("stuff" => 123, "foo" => "bar", "useful-id" => "baloney ")); $ Whoops-> pushHandler ($ ErrorPage); $ Whoops-> register (); lanciare una nuova RuntimeException ("Oopsie!"); ?>

Inoltre, poiché questo è semplicemente un gestore Whoops regolare, possiamo combinare gli altri gestori per ottenere risultati più dinamici. Immaginiamo che tu stia lavorando su un sito web AJAX + basato su JSON. In questo momento, se la tua applicazione dovesse fallire in qualche modo, ti verrebbe fuori un pugno di codice HTML sgradevole, quando ti aspettavi JSON. Nessun grosso problema:

 pushHandler (new Whoops \ Handler \ PrettyPageHandler ()); $ whoops-> pushHandler (new Whoops \ Handler \ JsonResponseHandler ()); $ Whoops-> register (); lanciare una nuova RuntimeException ("Oopsie!");

Questo è tutto. Ora, se qualcosa non funziona durante una richiesta AJAX, Whoops risponderà con una risposta JSON che specifica l'errore. Se NON è una richiesta AJAX, continuerai a vedere la normale pagina di errore. Se si verifica un errore, Whoops filtrerà attraverso ciascuno dei gestori registrati (a partire dall'ultimo gestore da registrare) e darà loro la possibilità di analizzare, modificare e rispondere alla richiesta.

Ora che hai un'idea generale di come funziona Whoops, proviamo a costruire il nostro gestore con Whoops e il framework Laravel 4.


Whoops and Laravel 4

Laravel 4 bundle Whoops come gestore di eccezioni di base, abilitato di default in modalità di sviluppo, inclusa una combinazione di colori personalizzata di Dayle Rees:

Se non hai ancora installato Laravel, vai avanti e segui i passaggi dell'installazione. Laravel è coperto ampiamente da Nettuts + e Tuts + Premium, quindi qui troverai molto allenamento, se vuoi approfondire ulteriormente.

Per i prossimi passi, supporrò che tu sia in qualche modo a mio agio con le basi di Laravel 4. Tuttavia, anche se non lo sei, dovrebbe comunque essere facile da seguire.

Se sei in modalità di sviluppo (debug), Whoops è disponibile tramite il contenitore IoC come whoops, e pre-impostato con uno dei due gestori: PrettyPageHandler o JsonResponseHandler, come whoops.handler (gli stessi due di cui abbiamo appena parlato). Entrambi questi gestori espongono utili metodi aggiuntivi, come hai visto sopra con il PrettyPageHandler. Accedendo a questi servizi, possiamo iniziare a personalizzare la nostra esperienza Whoops all'interno del framework.

Per semplicità, nella tua app / routes.php file, collegiamoci al servizio Whoops e impostiamo un titolo di pagina personalizzato per le nostre pagine di errore:

 setPageTitle ("Houston, abbiamo un problema!"); // Imposta il link "open:" per i file nel nostro editor di scelta: $ whoopsDisplayHandler-> setEditor ("sublime");  Route :: get ('/', function () // Forza l'esecuzione fallita lanciando un'eccezione: lanciare una nuova RuntimeException ("Oopsie!");); ?>

Mancia: Whoops supporta alcuni editor di default e ti consente di implementare il supporto per te come preferisci. Per saperne di più qui.

Se ora accedi alla tua applicazione Laravel, verrai accolto con un messaggio di errore con il titolo della tua pagina personalizzata. Se fai clic sul percorso del file sopra la casella del codice, dovrebbe aprire il file di riferimento direttamente nel tuo editor o IDE di scelta. Quant'è fico? Inoltre, dal momento che possiamo raggiungere il gestore già configurato dal core Laravel, possiamo utilizzare le altre funzionalità che abbiamo imparato sopra. Ad esempio, possiamo aggiungere tabelle personalizzate (con PrettyPageHandler :: addDataTable) con informazioni utili sulla nostra applicazione.

Facciamo un altro esempio. Questo sarà il nostro primo tentativo di scrivere il nostro gestore personalizzato. Vogliamo ottenere tutti i frame dello stack per un'eccezione e rimuovere tutto ciò che non fa parte del nostro codice dell'applicazione. Sembra abbastanza semplice, giusto?

 pushHandler (function ($ exception, $ exceptionInspector, $ runInstance) // Ottieni la raccolta di frame stack per l'eccezione corrente: $ frames = $ exceptionInspector-> getFrames (); // Filtra i frame esistenti in modo da mantenere solo quelli all'interno l'app / cartella $ frames-> filter (function ($ frame) $ filePath = $ frame-> getFile (); // Corrisponde a qualsiasi percorso file contenente / app / ... return preg_match ("/ \ / app \ /.+ / i ", $ filePath);); return Handler :: DONE;);  Route :: get ('/', function () // Forza l'esecuzione fallita lanciando un'eccezione: lanciare una nuova RuntimeException ("Oopsie!");); ?>

Mancia: In realtà non devi tornare Handler :: FATTO - questo serve solo a uno scopo semantico. Se vuoi che Whoops interrompa l'esecuzione di eventuali gestori extra dopo il tuo, scrivi return Handler :: LAST_HANDLER. Se vuoi che Whoops esca dall'esecuzione dello script dopo il tuo gestore, return Handler :: QUIT.

Puoi vedere che è straordinariamente conciso. Urla \ Run'S pushHandler il metodo accetta una chiusura che riceve fino a tre argomenti: l'oggetto eccezione, un ispettore delle eccezioni, che espone alcuni metodi di utilità a, hai indovinato, ispeziona le eccezioni e il Urla \ Run istanza che ha catturato l'eccezione. Attraverso questo gestore, usiamo l'ispettore delle eccezioni per estrarre i frame dello stack, il tutto in un modo accurato FrameCollection oggetto:

 getFrames (); // # => Whoops \ Exception \ FrameCollection; contare ($ fotogrammi); # => int foreach ($ frame come $ frame) get_class ($ frame); // # => Whoops \ Exception \ Frame stampa $ frame-> getFile (). ":". $ frame-> getLine (). "\ N"; # => "/path/to/file.php:123"?>

Mancia: Whoops converte internamente chiusure in un gestore speciale: Urla \ Handler \ CallbackHandler.

Puoi contare, iterare, mappare e filtrare il contenuto di questa classe, con l'interessante ma importante aspetto che la mappa e le operazioni filtro cambiano l'oggetto sul posto. Ciò significa che entrambe queste operazioni modificano direttamente l'istanza originale, invece di creare una nuova raccolta. Come è importante? Significa che i gestori possono eseguire più facilmente le modifiche che si propagano verso il basso a tutti gli altri gestori nello stack. Questo è esattamente ciò che abbiamo fatto con il nostro semplice gestore di cui sopra. Se ora esegui nuovamente lo script, vedrai che otterremo un elenco più breve di frame dello stack, solo per quanto riguarda il codice che vive all'interno della nostra directory dell'applicazione.

Per quanto riguarda l'oggetto Frame, stesso (Urla \ Exception \ Telaio), espone un insieme di metodi per raccogliere informazioni sul contenuto del frame (il percorso del file, il numero di riga, il metodo o la chiamata di funzione, il nome della classe, ecc.) e metodi che consentono di allegare commenti ai singoli frame dello stack. Un commento Frame è una funzionalità utile in Whoops che consente ai gestori di fornire informazioni aggiuntive raccolte da un'eccezione allegando le note direttamente ai singoli frame nello stack. Gestori come il PrettyPageHandler, per esempio, può quindi raccogliere quei commenti e visualizzarli insieme al percorso del file del frame e al numero di riga.

 pushHandler (function ($ exception, $ exceptionInspector, $ runInstance) foreach ($ exceptionInspector-> getFrames () come $ i => $ frame) $ frame-> addComment ("Questo è il numero di frame $ i");  return Handler :: DONE;); ?>

I commenti ai frame possono anche ricevere un secondo scopo discussione. Se si dispone di più gestori personalizzati, è possibile, ad esempio, filtrare i commenti dei frame con questo argomento per raccogliere solo le informazioni che ci interessano.

 getFrames (); foreach ($ frame come $ frame) // Questo frame era all'interno di una classe controller? (termina in Controller) $ className = $ frame-> getClass (); if (substr ($ className, -10) == "Controller") $ frame-> addComment ("Questo frame è all'interno di un controller: $ className", "controller-error");  // Successivamente, in un altro gestore, ottenere tutti i commenti nell'ambito dell'ambito 'controller-errors': $ controllerErrors = $ frame-> getComments ("controller-errors"); // # => array?>

Anche di interesse, il PrettyPageHandler naturalmente HTML-sfugge ai commenti del frame prima di visualizzarli, ma acquisisce intelligentemente gli URI nel corpo del commento e li converte in elementi di ancoraggio cliccabili. Vuoi collegare i frame alla documentazione o ai repository GitHub? È abbastanza facile; creiamo la nostra classe di gestori per questo esempio.

Mancia: Usare la tua classe invece di una chiusura ti offre un controllo extra sul tuo gestore, per non parlare del fatto che è più facile coprire i test automatici. Le tue classi di gestori personalizzati devono implementare il Urla \ Handler \ HandlerInterface interfaccia, ma puoi semplicemente estendere il Urla \ Handler \ Handler classe, e implementare il mancante maniglia metodo, come mostrato nell'esempio seguente.

 GetInspector () -> getFrames (); foreach ($ frame come $ frame) $ file = $ frame-> getFile (); $ line = $ frame-> getLine (); // Alcuni frame potrebbero non avere un percorso di file, ad esempio se si trovava in // a Closure, quindi dovremo verificarlo: if (! $ File) continua; // Controlla se il percorso del file per questo frame era all'interno della directory laravel / framework //, all'interno della directory del fornitore / Composer, e usa una regex capture // per estrarre solo le parti che vogliamo: if (preg_match ("/ \ / vendor \ / laravel \ / framework \ / (. +) $ / ", $ file, $ corrisponde)) $ percorso = $ corrisponde a [1]; // La prima corrispondenza è l'intero percorso, la seconda è la nostra acquisizione $ url = "$ this-> repoBase / $ path"; // Possiamo anche collegarci direttamente a un numero di linea, se ce l'abbiamo. Github // supporta questo aggiungendo #L alla fine dell'URL: if ($ line! == null) $ url. = "#L $ line";  $ frame-> addComment ($ url, "github-linker");  return handler :: DONE; ?>

È così, per quanto riguarda il nostro gestore. Metti questa classe da qualche parte nel tuo progetto e tutto ciò che resta da fare è abilitare e provare:

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

Con solo una manciata di linee di codice, abbiamo aggiunto un ulteriore livello di funzionalità (forse inutile, ma, ehi, è un esempio) alle nostre pagine di errore. Ecco alcune idee in più, se stai cercando una sfida:

  • Imballa il tuo gestore di errori personalizzato come fornitore di servizi Laravel.
  • Stai usando Git per gestire il tuo progetto? Costruisci un gestore personalizzato che si aggancia git-colpa per determinare chi l'ultima persona a toccare quel file che continua a lanciare un'eccezione (e urlargli contro) era, direttamente dalla pagina di errore.
  • Se ti senti coraggioso, usa PHP-Parser di nikic per analizzare il codice fastidioso e fornire suggerimenti per le correzioni (prometto che non è così complicato come sembra).

Pensieri finali

Spero che questa breve guida ti abbia aiutato a comprendere il tipo di possibilità che questa libreria consente nei tuoi progetti di tutti i giorni. Per ulteriori informazioni, consultare la documentazione completa dell'API.

Whoops è indipendente dalla struttura, leggero e, credo, abbastanza potente nella sua semplicità e si concentra su piccoli strumenti mix-and-matching. È anche open source e aperto a suggerimenti e miglioramenti. Se desideri contribuire o segnalare un bug, vai al repository ufficiale!