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.
composer require coisa/error-handlerUse 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.
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.
| 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.
- 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 genericInternal Server Errorbody. 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.
- Complete cookbook, application setup and bounded example verification.
- Source documentation, web documentation and API reference.
- Portable
coisa-error-handlerconsumer skill with complete application examples; optional installation remains a consumer choice. - Packagist, release history and repository.
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.