Skip to content

Repository files navigation

CoiSA Error Handler

Report PHP errors and throwables through application-owned handlers. Add native PHP callbacks, PSR-3 logging, PSR-14 events or PSR-15 HTTP middleware when needed.

PHP Version Composer Package Tests Docs License

📦 Installation

composer require coisa/error-handler

Use Composer 2 with PHP ^8.3; CI targets PHP 8.3–8.5. FastForward Container ^1.10 is a runtime dependency. Applications supply their logger, dispatcher, HTTP factories and response emitter as needed.

Match the documentation to your installed package and its release history. For an upgrade from 2.x, follow the migration guide and compare the 2.x API.

🛠️ Quick start

Create report.php beside your application's vendor/ directory:

<?php

declare(strict_types=1);

use CoiSA\ErrorHandler\ErrorHandler;

require __DIR__ . '/vendor/autoload.php';

$reports = [];

/**
 * Retain the synthetic failure without public diagnostic output.
 *
 * @param Throwable $error the failure to report
 */
$reporter = static function (Throwable $error) use (&$reports): void {
    $reports[] = $error;
};

$errors = new ErrorHandler($reporter);
$failure = new RuntimeException('Example failure');

$errors->handleThrowable($failure);

echo count($reports) . ' report; execution continued' . PHP_EOL;

Run php report.php; it prints 1 report; execution continued. Construction installs no PHP callbacks, and direct reporting returns when the reporter returns. Reporter failures propagate. Replace the in-memory reporter with your application's private diagnostic sink.

All three constructor inputs accept the matching handler interface or a callable; omitted PHP-error and shutdown inputs retain their defaults. Existing interface objects keep their identity. See the complete three-callback recipe.

🧰 Choose an integration

Need Entry point and guide
Report a throwable ErrorHandler::handleThrowable() and reporter composition.
Format terminal diagnostics Symfony CLI handler and Console ownership.
Handle warnings or uncaught exceptions register() / unregister() and native callbacks.
Send diagnostics to a logger or dispatcher PSR-3 logging and PSR-14 events.
Filter or fan out Filtering, aggregates and best effort.
Use a container Interop/FastForward provider, overrides and fresh scopes.
Return an HTTP response PSR-15 middleware and PSR-17 composition.
Return JSON with one private report Opt-in JSON rendering and complete recipe.
Use Interop/FastForward providers Request-aware provider and complete provider recipe.
Return public or diagnostic HTML Symfony HTML and complete recipe.
Select optional Whoops diagnostics Development HTML configuration and complete provider recipe.

One Interop provider supplies lifecycle services and request-aware responses. It selects JSON Problem Details or Symfony HTML when accepted and a generic fallback otherwise. Trusted debug enables diagnostic HTML/JSON; optional Whoops requires an explicit override. Debug never forces HTML. Applications supply PSR-17 implementations and a private reporter through container($application, ErrorHandlerServiceProvider::class).

Every response factory receives the original Throwable and current ServerRequestInterface. Middleware reports once before rendering; do not add the 2.x reporting decorator. Direct JSON rendering uses Symfony Serializer; JSON and Whoops renderers remain available for explicit application pipelines.

Lifecycle and HTTP boundaries

  • PHP callbacks are process-wide. Use distinct handlers for nested scopes and unregister in reverse order. Only the active owner receives shutdown reporting; PHP still retains registered shutdown callbacks until process exit.
  • A successfully reported globally uncaught throwable exits with status 1. Direct handleThrowable() calls return normally. Fatal errors remain fatal.
  • FastForward caches services and discovery installs no callbacks. Middleware has a separate handler; invoke the reusable factory for each independent scope.
  • Middleware reports once, then passes the current request to its pure renderer. The default provider negotiates its representation from Accept; missing or unsupported preferences use the generic Internal Server Error body. Codes 400–599 are preserved and reason phrases come from PSR-17. Reporter echo can still leak outside the response and corrupt emission; keep diagnostics private.
  • Output capture is an explicit public-renderer adapter: empty output uses the generic body and "0" remains valid. Reporters must keep diagnostics private.

See the HTTP contract and lifecycle guide for failure propagation, callback ownership and output-buffer limits.

📚 Guides and examples

🤝 Contributing

For suspected vulnerabilities, follow the security policy and use the private reporting channel. Ordinary bugs and feature requests belong in issues.

Follow the contributor guide for dependency setup and composer --no-plugins check. See testing for process fixtures and platform evidence, and the release process for independent release notes and reviewed version PRs. Release automation uses the Fast Forward Changelog reusable workflow without adding a runtime or Node dependency.

License

MIT, by Felipe Sayão Lobato Abreu.

Releases

Used by

Contributors

Languages