Whoops PHP Error Handling Framework

repository·master·Indexed 12 days ago

https://github.com/filp/whoops

A flexible, stack-based error handling framework for PHP that provides a highly visual error interface for web development and supports CLI and API error reporting. It includes built-in handlers such as PrettyPageHandler for rich HTML pages, JsonResponseHandler for APIs, and PlainTextHandler for CLI, along with tools for inspecting exceptions and manipulating stack frames via Whoops\Exception\Inspector.

Tokens
10.3K
Snippets
34
Records
46
Agent score
95%

What's inside Whoops

  1. How Whoops error handling works

    master

    Whoops is a stack-based error handling framework. You create an instance of Whoops\Run and push one or more handlers onto the stack using pushHandler(). When an error occurs, Whoops iterates through the handlers until one successfully processes the exception.

    Capturing HTML output manually

    If you want to collect the generated HTML instead of letting Whoops output it directly to the browser, you can disable quitting and direct output:

    $whoops = new \Whoops\Run;
    $whoops->allowQuit(false);
    $whoops->writeToOutput(false);
    $whoops->pushHandler(new \Whoops\Handler\PrettyPageHandler);
    $html = $whoops->handleException($e);
  2. Implement a custom Whoops handler

    master

    To create a custom handler, implement the Whoops\Handler\HandlerInterface or extend the Whoops\Handler\Handler abstract class.

    Your handler must implement the handle() method. Within handle(), you can signal how the handler stack should proceed using the Whoops\Handler\Handler constants:

    • Handler::DONE: Do nothing and continue to the next handler.
    • Handler::LAST_HANDLER: Stop executing any further handlers in the stack.
    • Handler::QUIT: Terminate script execution immediately.

    Handlers are provided with the Run instance, the Inspector instance, and the Exception being handled via setRun(), setInspector(), and setException() respectively.

    use Whoops\Handler\Handler;
    use Whoops\Handler\HandlerInterface;
    
    class MyCustomHandler implements HandlerInterface {
        public function handle(): int {
            // ... logic ...
            return Handler::LAST_HANDLER;
        }
        // ... setRun, setInspector, setException ...
    }
  3. Replay production errors in a development environment

    master

    You can replay errors that occurred in a production environment by serializing the exception and storing it. To replay the error in a local development environment using Whoops, unserialize the exception and pass it to the handleException() method of a Whoops\Run instance configured with a handler (such as PrettyPageHandler).

    $serialized_exception = serialize(new Exception('Something has happened!'));
    
    // Later, in your development environment:
    $whoops = new \Whoops\Run;
    $whoops->pushHandler(new \Whoops\Handler\PrettyPageHandler);
    $whoops->register();
    $whoops->handleException(unserialize($serialized_exception));
  4. How to create a Whoops integration for a framework

    master

    Whoops prefers that framework-specific integrations are maintained in separate repositories rather than within the Whoops core. To create an official integration:

    1. Maintain your integration classes and documentation in your own repository.
    2. Create a composer.json file in your repository that requires filp/whoops.
    3. Register your package with Packagist.
    4. Once published, create an issue in the Whoops repository so a link to your integration can be added to the Whoops README.

    Framework users can then install your integration via Composer, which will automatically pull in the required filp/whoops dependency.

    {
        "name": "username/whoops-someframework",
        "description": "Integrates the Whoops library into SomeFramework",
        "require": {
            "filp/whoops": "1.*
        }
    }
  5. Open referenced files in an editor using PrettyPageHandler

    master

    When using the PrettyPageHandler, you can configure Whoops to open the files referenced in an error directly in your IDE or editor. This feature requires that your PHP source files are locally accessible on the machine where the editor is installed.

    To enable this, use the setEditor() method on your PrettyPageHandler instance and pass the identifier for your preferred editor.

    <?php
    
    use Whoops//
    use Whoops\Handler\PrettyPageHandler;
    
    $handler = new PrettyPageHandler;
    $handler->setEditor('sublime');
  6. Install and register Whoops

    master

    To use Whoops in a standalone PHP project, install it via Composer and register the PrettyPageHandler to enable a visual error interface.

    1. Install the package:

      composer require filp/whoops
    2. Register the handler in your application entry point:

      $whoops = new //Whoops/Run;
      $whoops->pushHandler(new //Whoops/Handler/PrettyPageHandler);
      $whoops->register();
    composer require filp/whoops
  7. FrameCollection is a read-only collection

    master
    While Whoops\Exception\FrameCollection implements ArrayAccess, it is designed to be read-only. Attempting to use offsetSet or offsetUnset (e.g., $collection[0] = $newFrame; or unset($collection[0]);) will throw a generic \Exception with the message Whoops\Exception\FrameCollection is read only.
  8. Configure the PrettyPageHandler

    master

    The PrettyPageHandler renders a user-friendly HTML error page. You can customize its appearance, behavior, and the data it displays.

    Customizing Appearance

    • Page Title: Use setPageTitle($title) to change the title displayed in the browser tab and header.
    • Custom CSS: Use addCustomCss($name) to load an additional CSS file from your resource paths.
    • Custom JS: Use addCustomJs($name) to load an additional JavaScript file from your resource paths.

    Customizing Data Display

    By default, the handler displays superglobals like $_GET, $_POST, etc. You can add your own data tables to the error page:

    • Static Data: Use addDataTable($label, array $data) to add a table with a fixed associative array.
    • Dynamic Data: Use addDataDataTableCallback($label, callable $callback) to add a table where the content is generated lazily when the error is rendered. The callback receives the Whoops\Inspector\InspectorInterface as an argument.

    Security and Privacy

    To prevent sensitive information from being displayed in the error page, you can hide specific keys from superglobal arrays using blacklist($superGlobalName, $key) or hideSuperglobalKey($superGlobalName, $key).

    Example superglobal names: '_GET', '_POST', '_FILES', '_COOKIE', '_SESSION', '_SERVER', '_ENV'.

    $handler = new Whoops\Handler\PrettyPageHandler();
    
    // Customize appearance
    $handler->setPageTitle('My App Error');
    $handler->addCustomCss('my-styles.css');
    
    // Add custom data
    $handler->addDataTable('App Version', ['version' => '1.2.3']);
    $handler->addDataTableCallback('User Context', function ($inspector) {
        return ['user_id' => 42, 'role' => 'admin'];
    });
    
    // Hide sensitive data
    $handler->blacklist('_SERVER', 'PHP_AUTH_PW');
  9. Use `Whoops\Handler\CallbackHandler` for quick prototyping

    master

    The CallbackHandler allows you to use a standard PHP closure as a Whoops handler. This is useful for simple logic or quick debugging without creating a full class.

    When you pass a closure to Whoops\Run::appendHandler() or prependHandler(), Whoops automatically wraps it in a CallbackHandler.

    use Whoops\Handler\Handler;
    
    $run->appendHandler(function($exception, $inspector, $run) {
        var_dump($exception->getMessage());
        return Handler::DONE;
    });
  10. Configure IntelliJ Platform support with file mapping and Ajax

    master

    To support the IntelliJ Platform (like PhpStorm) when your development server is remote, you can provide a custom handler that maps remote file paths to local paths and returns an array containing a URL and an ajax flag. The ajax flag is required to prevent the browser from navigating away from the error page.

    $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
            );
        }
    );
  11. Inspect exceptions with `Whoops\Exception\Inspector`

    master

    The Inspector class provides a high-level interface for examining an exception and its stack trace. It is useful for handlers that need to extract specific details about the error.

    Available methods:

    • getException(): Returns the original Exception object.
    • getExceptionName(): Returns the class name of the exception.
    • getExceptionMessage(): Returns the exception message.
    • getFrames(): Returns an iterator for all frames in the stack trace.