Hoppla! PHP-Fehler für Cool Kids

Whoops ist eine kleine Bibliothek, die als Composer-Paket verfügbar ist und in der Sie Fehler und Ausnahmen in Ihren PHP-Projekten behandeln können.

Sofort erhalten Sie eine elegante, intuitive und informative Fehlerseite, wenn in Ihrer Anwendung ein Problem auftritt. Besser noch, unter alledem ist dies ein sehr einfaches, aber flexibles Werkzeug, um mit Fehlern auf eine Weise umzugehen, die für alles, was Sie tun, Sinn macht.

Die Hauptmerkmale der Bibliothek sind:

  • Detaillierte und intuitive Seite für Fehler und Ausnahmen
  • Codeansicht für alle Frames
  • Konzentrieren Sie sich auf die Fehler- / Ausnahmeanalyse durch die Verwendung benutzerdefinierter, einfacher Middleware- / Handler
  • Unterstützung für JSON- und AJAX-Anfragen
  • Eingeschlossene Anbieter für Silex- und Zend-Projekte durch die gebündelten Anbieter und Bestandteil des Laravel 4-Kerns
  • Saubere, kompakte und getestete Codebasis, ohne zusätzliche Abhängigkeiten

Whoops erreicht dies durch ein System von gestapelten Handlern. Sie sagen Whoops, welche Handler Sie verwenden möchten (Sie können aus den enthaltenen Handlern auswählen oder eigene erstellen), und wenn etwas passiert, haben alle Handler die Möglichkeit, etwas zu tun - dies kann alles von der Analyse der error (Whoops erleichtert das Extrahieren aussagekräftiger Informationen aus einem Fehler oder einer Ausnahme), um hilfreiche Fehlerbildschirme anzuzeigen (wie das integrierte) PrettyPageHandler, das gibt Ihnen die cool aussehende Seite (oben abgebildet).

Versuchen wir es zuerst, indem wir uns die Grundlagen ansehen und dann versuchen, unseren eigenen Handler mit Whoops und dem Laravel-Framework zu bauen. Für diesen kurzen Leitfaden gehe ich davon aus, dass Sie mit PHP einigermaßen vertraut sind und von Composer gehört haben. Sollte dies nicht der Fall sein, lesen Sie bitte hier bei Nettuts nach+.


Whoops installieren

Erstellen Sie ein Verzeichnis für Ihr Projekt, ändern Sie es, erstellen Sie ein composer.json Datei mit der Whoops-Anforderung und installieren Sie es. Whoops (ab Version 1.0.5) hat keine Abhängigkeiten, daher dauert dies nur eine Sekunde.

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

Whoops benutzen: Die Grundlagen

Um diese schlanke Fehlerseite in Aktion zu sehen, lassen Sie uns Whoops einrichten und sicherstellen, dass etwas kaputt geht, indem Sie eine Ausnahme in unserem Code auslösen. Erstellen Sie eine Datei im Verzeichnis Ihres Projekts. Sagen wir für dieses Handbuch, dass es heißt, index.php.

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

Da wir Whoops mit Composer installiert haben und PSR-0-kompatibel sind, benötigen wir nur den Composer-Autoloader, und wir können die Bibliothek in unserem eigenen Code verwenden!

 PushHandler (neuer Whoops \ Handler \ PrettyPageHandler ()); // Setze Whoops als Standardfehler- und Exception-Handler, der von PHP verwendet wird: $ whoops-> register (); Neue RuntimeException werfen ("Oopsie!"); ?>

Wenn Sie bereits über einen Webserver verfügen, greifen Sie auf die gerade erstellte Datei zu. Vergessen Sie nicht: Wenn Sie mit PHP 5.4 arbeiten, können Sie den integrierten Entwicklungsserver wie folgt nutzen:

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

Das wirst du bekommen:

Ziemlich ordentlich, richtig? Handler selbst können Optionen aufzeigen, um ihr Verhalten zu ändern oder zu verbessern. Sie können unter anderem den Titel der Standardfehlerseite festlegen und sogar zusätzliche Informationen einfügen:

 setPageTitle ("Es ist kaputt!"); // Setzt den Seitentitel $ errorPage-> setEditor ("sublime"); // Den für den "Open" -Link verwendeten Editor setzen $ errorPage-> addDataTable ("Extra Info", Array ("stuff" => 123, "foo" => "bar"), "nützlich-id" => " ")); $ whoops-> pushHandler ($ errorPage); $ whoops-> register (); Neue RuntimeException werfen ("Oopsie!"); ?>

Da dies lediglich ein normaler Whoops-Handler ist, können wir uns mit anderen Handlern mischen, um dynamischere Ergebnisse zu erzielen. Stellen Sie sich vor, Sie arbeiten an einer AJAX + JSON-basierten Website. Wenn Ihre Anwendung in irgendeiner Weise fehlschlägt, werden Sie eine Menge böser HTML-Dateien erhalten, wenn Sie JSON erwarten. Keine große Sache:

 PushHandler (neuer Whoops \ Handler \ PrettyPageHandler ()); $ whoops-> pushHandler (neuer Whoops \ Handler \ JsonResponseHandler ()); $ whoops-> register (); Neue RuntimeException werfen ("Oopsie!");

Das ist es. Wenn nun während einer AJAX-Anforderung etwas fehlschlägt, antwortet Whoops mit einer JSON-Antwort, in der der Fehler detailliert beschrieben wird. Wenn es sich nicht um eine AJAX-Anforderung handelt, wird weiterhin die reguläre Fehlerseite angezeigt. Wenn ein Fehler auftritt, filtert Whoops alle registrierten Handler (beginnend mit dem letzten registrierten Handler) und gibt ihnen die Möglichkeit, die Anforderung zu analysieren, zu ändern und auf sie zu reagieren.

Nun, da Sie eine allgemeine Vorstellung davon haben, wie Whoops funktioniert, können Sie jetzt einen eigenen Handler mit Whoops und dem Laravel 4-Framework erstellen.


Whoops und Laravel 4

Laravel 4 bündelt Whoops als zentralen Ausnahmebehandler, der standardmäßig im Entwicklungsmodus aktiviert ist, einschließlich eines benutzerdefinierten Farbschemas von Dayle Rees:

Wenn Sie Laravel noch nicht installiert haben, befolgen Sie die Installationsschritte. Laravel ist auf Nettuts + und Tuts + Premium ausführlich beschrieben. Sie finden hier also reichlich Training, wenn Sie sich weiter einkaufen möchten.

Für die nächsten Schritte gehe ich davon aus, dass Sie mit den Grundlagen von Laravel 4 einigermaßen vertraut sind. Selbst wenn Sie es nicht sind, sollte es dennoch leicht zu befolgen sein.

Wenn Sie sich im Entwicklungsmodus (Debug-Modus) befinden, ist Whoops über den IoC-Container als verfügbar Hoppla, und mit einem von zwei Handlern voreingestellt: PrettyPageHandler oder JsonResponseHandler, wie whoops.handler (die gleichen zwei, über die wir gerade gesprochen haben). Beide Handler stellen nützliche zusätzliche Methoden bereit, wie Sie oben mit der PrettyPageHandler. Durch den Zugriff auf diese Dienste können wir unsere Whoops-Erfahrung innerhalb des Frameworks anpassen.

Der Einfachheit halber in Ihrem app / routes.php Datei, lass uns in den Whoops-Dienst einhaken und einen benutzerdefinierten Seitentitel für unsere Fehlerseiten festlegen:

 setPageTitle ("Houston, wir haben ein Problem!"); // Setz den "open:" - Link für Dateien auf den Editor deiner Wahl: $ whoopsDisplayHandler-> setEditor ("sublime");  Route :: get ('/', function () // Erzwingen Sie das Fehlschlagen der Ausführung, indem Sie eine Ausnahme auslösen: werfen Sie eine neue RuntimeException ("Oopsie!");); ?>

Spitze: Whoops unterstützt standardmäßig einige Editoren und ermöglicht es Ihnen, die Unterstützung nach Ihren Wünschen zu implementieren. Lesen Sie hier mehr darüber.

Wenn Sie jetzt auf Ihre Laravel-Anwendung zugreifen, wird eine Fehlermeldung mit Ihrem benutzerdefinierten Seitentitel angezeigt. Wenn Sie auf den Dateipfad über dem Codefeld klicken, sollte die referenzierte Datei direkt in Ihrem Editor oder der gewünschten IDE geöffnet werden. Wie cool ist das? Da wir den bereits durch den Laravel-Kernel eingerichteten Handler erreichen können, können wir auch die anderen Funktionen nutzen, über die wir uns oben informiert haben. Zum Beispiel können wir benutzerdefinierte Tabellen hinzufügen (mit PrettyPageHandler :: addDataTable) mit nützlichen Informationen zu unserer Anwendung.

Lassen Sie uns noch ein Beispiel anschauen. Dies ist unser erster Versuch, unseren eigenen benutzerdefinierten Handler zu schreiben. Wir möchten alle Stack-Frames für eine Ausnahme abrufen und alles entfernen, was nicht Teil unseres Anwendungscodes ist. Klingt einfach genug, richtig?

 pushHandler (Funktion ($ exception, $ exceptionInspector, $ runInstance) // Liefert die Sammlung von Stack-Frames für die aktuelle Exception: $ frames = $ exceptionInspector-> getFrames (); //) Bestehende Frames filtern, damit nur die Frames darin bleiben der app / Ordner $ frames-> filter (Funktion ($ frame) $ filePath = $ frame-> getFile (); // entspricht einem beliebigen Dateipfad, der / app /… enthält, und gibt preg_match zurück ("/ \ / app \ /.+.) / i ", $ filePath);); return Handler :: DONE;);  Route :: get ('/', function () // Erzwingen Sie das Fehlschlagen der Ausführung, indem Sie eine Ausnahme auslösen: werfen Sie neue RuntimeException ("Oopsie!");); ?>

Spitze: Sie müssen nicht wirklich zurückkehren Handler :: DONE - Dies dient nur einem semantischen Zweck. Wenn Sie möchten, dass Whoops nach den Ihren keine zusätzlichen Handler mehr ausführt, schreiben Sie return Handler :: LAST_HANDLER. Wenn Sie möchten, dass Whoops die Skriptausführung nach Ihrem Handler beendet, return Handler :: QUIT.

Sie können sehen, dass es bemerkenswert kurz ist. Whoops \ Run's PushHandler Die Methode akzeptiert eine Schließung, die bis zu drei Argumente empfängt: das Exception-Objekt, einen Exception-Inspector, der einige Utility-Methoden verfügbar macht, Sie haben es erraten, Exceptions prüfen und die Whoops \ Run Instanz, die die Ausnahme erfasst hat. Über diesen Handler extrahieren wir mit Hilfe des Exception Inspectors die Stack-Frames, alles in einem ordentlichen Bereich FrameCollection Objekt:

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

Spitze: Whoops wandelt Verschlüsse intern in einen speziellen Handler um: Whoops \ Handler \ CallbackHandler.

Sie können den Inhalt dieser Klasse zählen, iterieren, zuordnen und filtern. Der interessante, aber wichtige Aspekt besteht darin, dass die Map- und Filteroperationen das Objekt an Ort und Stelle verändern. Dies bedeutet, dass diese beiden Vorgänge die ursprüngliche Instanz direkt ändern, anstatt eine neue Sammlung zu erstellen. Wie ist das wichtig? Das bedeutet, dass Handler leichter Änderungen durchführen können, die sich nach unten auf alle anderen Handler im Stapel ausbreiten. Genau das haben wir mit unserem einfachen Handler oben gemacht. Wenn Sie das Skript jetzt erneut ausführen, sehen Sie, dass wir eine kürzere Liste von Stackframes erhalten, die nur den Code betrifft, der in unserem Anwendungsverzeichnis enthalten ist.

Wie für das Frame-Objekt selbst (Whoops \ Exception \ Frame), es stellt eine Reihe von Methoden zur Verfügung, um Informationen über den Inhalt des Frames (den Dateipfad, die Zeilennummer, die Methode oder den Funktionsaufruf, den Klassennamen usw.) zu sammeln, sowie Methoden, mit denen Sie Kommentare an einzelne Stack-Frames anhängen können. Ein Frame-Kommentar ist eine nützliche Funktion in Whoops, mit der Handler zusätzliche Informationen bereitstellen können, die sie aus einer Ausnahme sammeln, indem Notizen direkt an einzelne Frames im Stapel angehängt werden. Handler wie die PrettyPageHandler, Sie können diese Kommentare beispielsweise sammeln und zusammen mit dem Dateipfad und der Zeilennummer des Rahmens anzeigen.

 pushHandler (Funktion ($ exception, $ exceptionInspector, $ runInstance) foreach ($ exceptionInspector-> getFrames () als $ i => $ frame) $ frame-> addComment ("Dies ist die Frame-Nummer $ i");  return Handler :: DONE;); ?>

Rahmenkommentare erhalten möglicherweise eine zweite Umfang Streit. Wenn Sie über mehrere benutzerdefinierte Handler verfügen, können Sie beispielsweise Frame-Kommentare nach diesem Argument filtern, um nur die Informationen zu sammeln, die Sie interessieren.

 getFrames (); foreach ($ frames as $ frame) // War dieser Frame in einer Controller-Klasse? (endet in Controller) $ className = $ frame-> getClass (); if (substr ($ className, -10) == "Controller") $ frame-> addComment ("Dieser Frame befindet sich in einem Controller: $ className", "controller-error");  // Später erhalten Sie in einem anderen Handler alle Kommentare im Bereich 'Controller-errors': $ controllerErrors = $ frame-> getComments ("controller-errors"); // # => array?>

Interessant ist auch die PrettyPageHandler Natürlich entgeht HTML den Rahmenkommentaren, bevor sie angezeigt werden, erfasst jedoch URIs intelligent im Kommentarkörper und konvertiert sie in anklickbare Ankerelemente. Möchten Sie Frames mit Dokumentation oder mit GitHub-Repositorys verknüpfen? Es ist leicht genug; Lassen Sie uns für dieses Beispiel eine eigene Handler-Klasse erstellen.

Spitze: Wenn Sie anstelle eines Abschlusses eine eigene Klasse verwenden, haben Sie zusätzliche Kontrolle über Ihren Handler - ganz zu schweigen von der Vereinfachung der Abdeckung durch automatisierte Tests. Ihre benutzerdefinierten Handler-Klassen müssen das implementieren Whoops \ Handler \ HandlerInterface Schnittstelle, aber Sie können stattdessen einfach die Whoops \ Handler \ Handler Klasse und implementieren die fehlenden Griff wie im nachstehenden Beispiel gezeigt.

 getInspector () -> getFrames (); foreach ($ frames als $ frame) $ file = $ frame-> getFile (); $ line = $ frame-> getLine (); // Einige Frames verfügen möglicherweise nicht über einen Dateipfad, z. B. wenn sie innerhalb von // einer Schließung vorkamen. Daher müssen wir Folgendes prüfen: if (! $ File) continue; // Überprüfen Sie, ob der Dateipfad für diesen Frame im Verzeichnis laravel / framework // im Verzeichnis Composer Vendor / liegt, und verwenden Sie ein Regex-Capture //, um nur die gewünschten Teile zu extrahieren: if (preg_match ("/ \ / Hersteller \ / laravel \ / framework \ / (. +) $ / ", $ -Datei, $ -Matches)) $ path = $ -Matches [1]; // Der erste Treffer ist der ganze Pfad, der zweite ist unser Capture. $ Url = "$ this-> repoBase / $ path"; // Wir können auch direkt auf eine Zeilennummer verweisen, wenn wir sie haben. Github // unterstützt dies durch das Anhängen von #L bis zum Ende der URL: if ($ line! == null) $ url. = "#L $ line";  $ frame-> addComment ($ url, "github-linker");  return Handler :: DONE; ?>

Das ist es, soweit unser Handler geht. Platzieren Sie diese Klasse irgendwo in Ihrem Projekt, und Sie müssen sie nur noch aktivieren und ausprobieren:

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

Mit nur wenigen Zeilen Code haben wir unseren Fehlerseiten eine zusätzliche (möglicherweise nutzlose, aber hey, es ist ein Beispiel) Funktionalität hinzugefügt. Hier sind ein paar zusätzliche Ideen, wenn Sie nach einer Herausforderung suchen:

  • Packen Sie Ihren benutzerdefinierten Fehlerbehandler als Laravel-Dienstanbieter.
  • Verwenden Sie Git, um Ihr Projekt zu verwalten? Erstellen Sie einen benutzerdefinierten Handler, in den die Verbindung hergestellt wird Git-Schuld Um zu ermitteln, wer die letzte Person war, die diese Datei berührt hat und die eine Ausnahme auslöst (und sie anschreien), direkt von der Fehlerseite aus.
  • Wenn Sie sich mutig fühlen, verwenden Sie den PHP-Parser von nikic, um den problematischen Code zu analysieren und Vorschläge für Korrekturen zu geben (ich verspreche, dass es nicht so kompliziert ist, wie es klingt)..

Abschließende Gedanken

Ich hoffe, dass dieser kurze Leitfaden Ihnen geholfen hat, die Möglichkeiten zu verstehen, die diese Bibliothek in Ihren täglichen Projekten bietet. Weitere Informationen finden Sie in der vollständigen API-Dokumentation.

Whoops ist Framework-agnostisch, leichtgewichtig und meiner Meinung nach recht mächtig in seiner Einfachheit und fokussiert sich auf Mix-and-Matching-Werkzeuge. Es ist auch Open Source und offen für Vorschläge und Verbesserungen. Wenn Sie einen Fehler einbringen oder melden möchten, gehen Sie zum offiziellen Repository!