phphd/exception-handler
PHPhD Exception Handler offers a structured way to manage exceptions in Laravel/PHP applications, with configurable handling and cleaner error responses for more predictable debugging and user-facing failures.
Architecture fit. The package slots into Laravel's existing exception pipeline as a resolution layer: a registry of per-exception handlers, matched in registration order, each returning a Response or null to fall through to the framework default. This is a familiar pattern and maps cleanly onto how Laravel's native Handler/withExceptions() already works, so the conceptual delta is small. The Symfony Messenger lineage in the description suggests a message-driven or handler-bus resolution mechanism under the hood; for a TPM the relevant point is that it adds a dependency graph (Symfony component constraints) beyond vanilla Laravel, which is the thing to verify against the fleet's locked versions.
Integration feasibility. High on ergonomics, low on ceremony. composer require, package discovery auto-registers the provider, vendor:publish yields the config registry, and an artisan generator scaffolds handlers. That is textbook Laravel and means a competent Laravel engineer can produce a working spike in a day. The published config is the source of truth for ordering, which makes the behavior inspectable.
Technical risk. This is the crux. The handler sits in the failure path of every request and job — maximum blast radius for a dependency with 1 star, a composite score of 0.305, and a patch release whose only changelog content is a bare compare link. That is a thin maintenance signal, not proof of abandonment. Specific risks to price: no visible evidence of a CI matrix, test coverage, or supported Laravel/PHP versions; single-maintainer concentration; potential conflicts with Laravel 11+ native withExceptions() if both are wired; and the Symfony Messenger constraint surface. Because failures here corrupt error responses rather than break the happy path, bugs are discovered by customers.
Key questions to answer before adoption.
withExceptions(), or only convenience? If the latter, the risk may not be worth it.Stack fit. Best fit is a mid-size Laravel codebase with duplicated exception rendering/reporting across web, JSON API, and queued jobs, and a team without spare platform-engineering capacity. Poor fit if we are already standardized on Laravel 11+ withExceptions() and it meets the contract — in that case adopt the pattern, not the dependency.
Migration path. Do not big-bang this. Sequence:
instanceof chain (auth, domain validation, or a third-party API failure), keeping the native handler in place.Compatibility. Pin "phphd/exception-handler": "^1.1". Verify discovery behavior on our skeleton versions and add the provider explicitly where discovery is disabled. Critically, verify we do not double-register exceptions in both bootstrap/app.php and the package config — precedence then becomes non-obvious and debugging is expensive. Check the Symfony component constraints against composer lock files across the fleet.
Sequencing. The decision gate is the spike: if handler precedence, console/queue behavior, and config-cache behavior all pass under feature test, proceed to the adapter and a second service. If any of those is murky, stay on native Laravel and lift the pattern only.
Maintenance. Treat this as supply-chain risk, not a utility library. Single maintainer, low star count, and a patch release documented only by a diff link mean we cannot assume a support contract. Mitigations: pinned version, adapter seam, documented rollback to native withExceptions(), and a calendar review each minor bump because the handler contract is the most likely thing to shift. Budget a small, recurring line item for this stewardship.
Support. There is no commercial backing and no evidence of a large user community to lean on. Support burden falls on our own on-call. The compensation is that the code is MIT and small enough to vendor or fork if abandoned — but only if we own the adapter and understand the resolution pipeline.
Scaling. Two dimensions. First, registry growth: as handlers accumulate, precedence becomes the dominant source of bugs — list specific types first, a broad Throwable catch-all last, and prefer per-module registration so ownership stays local. Second, config caching: the registry is cached in production, so any registration change without config:clear/config:cache produces the classic "my handler doesn't run" incident.
Failure modes to design against.
ValidationException/AuthenticationException.getMessage()/getTraceAsString() reaching clients; log, return a stable code.withExceptions() making precedence non-deterministic.Ramp-up. Low for any Laravel engineer: the concepts (exception-to-response mapping, ordered resolution, report-vs-render separation) are familiar. The genuine learning is operational discipline, not API — precedence conventions, one owner per exception, report/don't-report judgment for expected control flow, and the debugging recipe of a temporary catch-all handler. Document those conventions once, enforce them in review, and the team is productive in about a sprint.
TPM verdict. The pattern is worth adopting; the dependency is not yet ready to become a platform-wide standard on a 1-star project sitting in the critical failure path. Recommended call: run a one-week spike behind an internal adapter in a non-critical service, read the 1.1.0→1.1.1 diff, confirm the version matrix, and only then decide between full adoption and implementing the same pattern natively on Laravel 11+.
How can I help you explore Laravel packages today?