Technical Documentation: filp/whoops
โน๏ธ Provenance: Multi-Tier Ingestion ยท CodeWiki Reference
Overview (README.md)
whoops
PHP errors for cool kids
whoops is an error handler framework for PHP. Out-of-the-box, it provides a pretty
error interface that helps you debug your web projects, but at heart it's a simple yet
powerful stacked error handling system.
Features
- Flexible, stack-based error handling
- Stand-alone library with (currently) no required dependencies
- Simple API for dealing with exceptions, trace frames & their data
- Includes a pretty rad error page for your webapp projects
- Includes the ability to open referenced files directly in your editor and IDE
- Includes handlers for different response formats (JSON, XML, SOAP)
- Easy to extend and integrate with existing libraries
- Clean, well-structured & tested code-base
Sponsors
Installing
If you use Laravel 4, Laravel 5.5+, Mezzio or ZubZet 1.2+, you already have Whoops. There are also community-provided instructions on how to integrate Whoops into
Silex 1,
Silex 2,
Phalcon,
Laravel 3,
Laravel 5,
CakePHP 3,
CakePHP 4,
Zend 2,
Zend 3,
Yii 1,
FuelPHP,
Slim,
Pimple,
Laminas,
or any framework consuming StackPHP middlewares
or PSR-7 middlewares.
If you are not using any of these frameworks, here's a very simple way to install:
Use Composer to install Whoops into your project:
bashcomposer require filp/whoopsRegister the pretty handler in your code:
php$whoops = new \Whoops\Run; $whoops->pushHandler(new \Whoops\Handler\PrettyPageHandler); $whoops->register();
For more options, have a look at the example files in examples/ to get a feel for how things work. Also take a look at the API Documentation and the list of available handlers below.
You may also want to override some system calls Whoops does. To do that, extend Whoops\Util\SystemFacade, override functions that you want and pass it as the argument to the Run constructor.
You may also collect the HTML generated to process it yourself:
$whoops = new \Whoops\Run;
$whoops->allowQuit(false);
$whoops->writeToOutput(false);
$whoops->pushHandler(new \Whoops\Handler\PrettyPageHandler);
$html = $whoops->handleException($e);Available Handlers
whoops currently ships with the following built-in handlers, available in the Whoops\Handler namespace:
PrettyPageHandler- Shows a pretty error page when something goes pants-upPlainTextHandler- Outputs plain text message for use in CLI applicationsCallbackHandler- Wraps a closure or other callable as a handler. You do not need to use this handler explicitly, whoops will automatically wrap any closure or callable you pass toWhoops\Run::pushHandlerJsonResponseHandler- Captures exceptions and returns information on them as a JSON string. Can be used to, for example, play nice with AJAX requests.XmlResponseHandler- Captures exceptions and returns information on them as a XML string. Can be used to, for example, play nice with AJAX requests.
You can also use pluggable handlers, such as SOAP handler.
Authors
This library was primarily developed by Filipe Dobreira, and is currently maintained by Denis Sokolov. A lot of awesome fixes and enhancements were also sent in by various contributors. Special thanks to Graham Campbell and Markus Staab for continuous participation.
API Documentation (`docs/API Documentation.md`)
API Documentation
Core Classes:
Whoops\Run- The mainWhoopsclass - represents the stack and current executionWhoops\Handler\HandlerandWhoops\Handler\HandlerInterface- Abstract representation of a Handler, and utility methodsWhoops\Exception\Inspector- Exposes methods to inspect an exceptionWhoops\Exception\FrameCollection- Exposes methods to work with a list of framesWhoops\Exception\Frame- Exposes methods to inspect a single stack trace frame from an exception
Core Handlers:
Whoops\Handler\CallbackHandler- Wraps regular closures as handlersWhoops\Handler\JsonResponseHandler- Formats errors and exceptions as a JSON payloadWhoops\Handler\PrettyPageHandler- Outputs a detailed, fancy error page
Core Functions:
Whoops\Util\Misc::isAjaxRequest()- Determines whether the current request was triggered by XMLHttpRequestWhoops\Util\Misc::isCommandLine()- Determines whether the current request was triggered via php commandline interface (CLI)
Core Classes:
`Whoops\Run`
The Run class models an instance of an execution, and integrates the methods to control whoops' execution in that context, and control the handlers stack.
Constants
string Run::EXCEPTION_HANDLER // (name for exception handler method)
string Run::ERROR_HANDLER // (name for error handler method)
string Run::SHUTDOWN_HANDLER // (name for shutdown handler method)Methods
/* Detailed source-code truncated for AI context efficiency. */`Whoops\Handler\Handler` & `Whoops\Handler\HandlerInterface`
This abstract class contains the base methods for concrete handler implementations. Custom handlers can extend it, or implement the Whoops\Handler\HandlerInterface interface.
Constants
int Handler::DONE // If returned from HandlerInterface::handle, does absolutely nothing.
int Handler::LAST_HANDLER // ...tells whoops to not execute any more handlers after this one.
int Handler::QUIT // ...tells whoops to quit script execution immediately.Methods
// Custom handlers should expose this method, which will be called once an
// exception needs to be handled. The Handler::* constants can be used to
// signal the underlying logic as to what to do next.
HandlerInterface::handle()
#=> null | int
// Sets the Run instance for this handler
HandlerInterface::setRun(Whoops\Run $run)
#=> null
// Sets the Inspector instance for this handler
HandlerInterface::setInspector(Whoops\Exception\Inspector $inspector)
#=> null
// Sets the Exception for this handler to handle
HandlerInterface::setException(Exception $exception)
#=> null`Whoops\Exception\Inspector`
The Inspector class provides methods to inspect an exception instance, with particular focus on its frames/stack-trace.
Methods
Inspector::__construct(Exception $exception)
#=> null
// Returns the Exception instance being inspected
Inspector::getException()
#=> Exception
// Returns the string name of the Exception being inspected
// A faster way of doing get_class($inspector->getException())
Inspector::getExceptionName()
#=> string
// Returns the string message for the Exception being inspected
// A faster way of doing $inspector->getException()->getMessage()
Inspector::getExceptionMessage()
#=> string
// Returns an iterator instance for all the frames in the stack
// trace for the Exception being inspected.
Inspector::getFrames()
#=> Whoops\Exception\FrameIterator`Whoops\Exception\FrameCollection`
The FrameCollection class exposes a fluent interface to manipulate and examine a
collection of Frame instances.
FrameCollection objects are serializable.
Methods
// Returns the number of frames in the collection
// May also be called as count($frameCollection)
FrameCollection::count()
#=> int
// Filter the Frames in the collection with a callable.
// The callable must accept a Frame object, and return
// true to keep it in the collection, or false not to.
FrameCollection::filter(callable $callable)
#=> FrameCollection
// See: array_map
// The callable must accept a Frame object, and return
// a Frame object, doesn't matter if it's the same or not
// - will throw an UnexpectedValueException if something
// else is returned.
FrameCollection::map(callable $callable)
#=> FrameCollection`Whoops\Exception\Frame`
The Frame class models a single frame in an exception's stack trace. You can use it to retrieve info about things such as frame context, file, line number. Additionally, you have available functionality to add comments to a frame, which is made available to other handlers.
Frame objects are serializable.
Methods
/* Detailed source-code truncated for AI context efficiency. */Core Handlers
`Whoops\Handler\CallbackHandler`
The CallbackHandler handler wraps regular PHP closures as valid handlers. Useful for quick prototypes or simple handlers. When you pass a closure to Run::pushHandler, it's automatically converted to a CallbackHandler instance.
<?php
use Whoops\Handler\Handler;
$run->pushHandler(function($exception, $inspector, $run) {
var_dump($exception->getMessage());
return Handler::DONE;
});
$run->popHandler() // #=> Whoops\Handler\CallbackHandlerMethods
// Accepts any valid callable
// For example, a closure, a string function name, an array
// in the format array($class, $method)
CallbackHandler::__construct($callable)
#=> null
CallbackHandler::handle()
#=> int | null`Whoops\Handler\JsonResponseHandler`
The JsonResponseHandler, upon receiving an exception to handle, simply constructs a JSON payload, and outputs it. Methods are available to control the detail of the output, and if it should only execute for AJAX requests - paired with another handler under it, such as the PrettyPageHandler, it allows you to have meaningful output for both regular and AJAX requests. Neat!
The JSON body has the following format:
{
"error": {
"type": "RuntimeException",
"message": "Something broke!",
"file": "/var/project/foo/bar.php",
"line": 22,
# if JsonResponseHandler::addTraceToOutput(true):
"trace": [
{ "file": "/var/project/foo/index.php",
"line": 157,
"function": "handleStuffs",
"class": "MyApplication\DoerOfThings",
"args": [ true, 10, "yay method arguments" ] },
# ... more frames here ...
]
}
}Methods
// Should detailed stack trace output also be added to the
// JSON payload body?
JsonResponseHandler::addTraceToOutput(bool $yes = null)
#=> bool
JsonResponseHandler::handle()
#=> int | null`Whoops\Handler\PrettyPageHandler`
The PrettyPageHandler generates a fancy, detailed error page which includes code views for all frames in the stack trace, environment details, etc. Super neat. It produces a bundled response string that does not require any further HTTP requests, so it's fit to work on pretty much any environment and framework that speaks back to a browser, without you having to explicitly hook it up to your framework/project's routing mechanisms.
Methods
/* Detailed source-code truncated for AI context efficiency. */Core Functions:
`Whoops\Util\Misc::isAjaxRequest()`
#=> boolean
// Use a certain handler only in AJAX triggered requests
if (Whoops\Util\Misc::isAjaxRequest()){
$run->addHandler($myHandler);
}`Whoops\Util\Misc::isCommandLine()`
#=> boolean
// Use a certain handler only in php cli
if (Whoops\Util\Misc::isCommandLine()){
$run->addHandler($myHandler);
}/*
Output the error message only if using command line.
else, output to logger if available.
Allow to safely add this handler to web pages.
*/
$plainTextHandler = new PlainTextHandler();
if (!Whoops\isCommandLine()){
$plainTextHandler->loggerOnly(true);
}
$run->addHandler($myHandler);Framework Integration (`docs/Framework Integration.md`)
Contributing an integration with a framework
Lately we're preferring to keep integration libraries out of the Whoops core.
If possible, consider managing an official Whoops-SomeFramework integration.
The procedure is not hard at all.
- Keep your integration classes and instructions in a repository of your own;
- Create a
composer.jsonfile in your repository with contents similar to the following:
{
"name": "username/whoops-someframework",
"description": "Integrates the Whoops library into SomeFramework",
"require": {
"filp/whoops": "1.*"
}
}Once that is done, please create an issue and we will add a link to it in our README.
SomeFramework users then would write this in their composer.json:
"require": {
"username/whoops-someframework": "*"
}This would also install Whoops and you'd be able to release updates to your package as quickly as you wish them to.
Open Files In An Editor (`docs/Open Files In An Editor.md`)
Open Files In An Editor
When using the pretty error page feature, whoops comes with the ability to
open referenced files directly in your IDE or editor.
This feature only works in case your php-source files are locally accessible to the machine on which the editor is installed.
<?php
use Whoops\Handler\PrettyPageHandler;
$handler = new PrettyPageHandler;
$handler->setEditor('sublime');The following editors are currently supported by default.
emacs- Emacsidea- IDEAmacvim- MacVimphpstorm- PhpStorm (on Linux you might need to manually install a handler)sublime- Sublime Text 2 and possibly 3 (on OS X you might need a special handler)textmate- Textmatexdebug- xdebug (uses xdebug.file_link_format)vscode- VSCode (ref Opening VS Code with URLs)atom- Atom (ref Add core URI handlers)espresso- Espressonetbeans- Netbeans (ref xdebug.file_link_format)
Adding your own editor is simple:
$handler->setEditor(function($file, $line) {
return "whatever://open?file=$file&line=$line";
});You can add IntelliJ Platform support like this:
$handler->setEditor(
function ($file, $line) {
// if your development server is not local it's good to map remote files to local
$translations = array('^' . __DIR__ => '~/Development/PhpStormOpener'); // change to your path
foreach ($translations as $from => $to) {
$file = preg_replace('#' . $from . '#', $to, $file, 1);
}
// IntelliJ platform requires that you send an Ajax request, else the browser will quit the page
return array(
'url' => "http://localhost:63342/api/file/?file=$file&line=$line",
'ajax' => true
);
}
);Replay Errors (`docs/Replay Errors.md`)
Replay Errors
You can replay Errors that happened in production if you serialize them and store them to later replay in a development Whoops:
$serialized_exception = serialize(new Exception('Something has happened!'));
$whoops = new \Whoops\Run;
$whoops->pushHandler(new \Whoops\Handler\PrettyPageHandler);
$whoops->register();
$whoops->handleException(unserialize($serialized_exception));https://github.com/filp/whoops/issues/623
--- METRICS ---
- Files Extracted: 5
- Estimated Token Budget: ~4468 tokens
- Canonical Reference: https://codewiki.google/github.com/filp/whoops