Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Api Problem Laravel Package

phpro/api-problem

A framework-agnostic RFC 7807 Problem Details implementation for PHP, providing an interface, an ApiProblemException, and built-in HTTP problem types (400–428) for consistent API error responses, with Symfony integration available.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit phpro/api-problem is a framework-agnostic value-object library, not a middleware or bundle. It defines ApiProblemInterface::toArray(), an ApiProblemException carrier, and ~13 prebuilt HTTP problem classes that auto-populate type/title from the status code. The README is explicit that "handling the exceptions is up to the framework," and the only listed integration is a Symfony bundle. In a Laravel codebase this means the package gives us a standardized error payload shape and a small type hierarchy, and nothing else — no service provider, no auto-discovery, no renderable, no application/problem+json content negotiation. That is actually a reasonable division of labor, but a TPM must budget for the glue code as first-party scope, not assume it ships with the dependency.

Integration feasibility Feasible and small. The realistic Laravel implementation is roughly 80–150 lines in one place: register renderables for ApiProblemException (and optionally map framework exceptions) in bootstrap/app.php (->withExceptions(...)) for Laravel 11+, or app/Exceptions/Handler.php for 10 and below; serialize toArray() via response()->json($payload, $status, ['Content-Type' => 'application/problem+json']). Custom problems are trivial to add by extending HttpApiProblem or implementing the interface.

Two concrete friction points:

  • ValidationApiProblem requires symfony/validator (a ConstraintViolationList), so it cannot consume Laravel's ValidationException directly. We either pull a Symfony component into a Laravel app purely as a DTO adapter or hand-roll a problem class for Laravel's validator output.
  • The package has no 429, 419, or 500-with-traceId convenience class; rate limiting and CSRF are common enough in Laravel that we'd write those ourselves.

Technical risk

  • Adoption/ecosystem risk (medium): 66 stars, 0 dependents. We would be among the first production consumers; unknown edge cases surface on our timeline, not the maintainer's.
  • Maintenance-mode signal (medium): releases 1.6 → 1.9 are almost entirely "allow PHP 8.2/8.3/8.4/8.5," i.e., compatibility bumps rather than feature work. The reported 2026-09-14 release date is anomalous and should be verified against Packagist before it appears in any dependency decision record.
  • Spec currency (low-medium): RFC 7807 was superseded by RFC 9457 (2023). The wire format is backward-compatible, but type/title guidance and media-type registration changed; committing to 7807 language in our public API contract now creates a small future docs/contract debt.
  • Debug leakage (high if misconfigured): ExceptionApiProblem embeds message, file, line, and full stack trace. Must be strictly gated on app.debug and excluded from any externally reachable environment.
  • Bus factor (medium): effectively one maintainer (veewee) plus drive-by contributors. MIT license and a tiny surface mean forking is cheap — mitigate by vendoring-friendly design.

Key questions

  1. Is our error envelope a public contract (documented, versioned, relied on by third-party clients) or internal-only? That determines whether this is a 2-day task or a 2-quarter compatibility program.
  2. Do we standardize on RFC 7807 as-is or RFC 9457 (application/problem+json, type as resolvable URI)? Decide once, document in the OpenAPI spec.
  3. Build vs. buy: is a ~120-line in-house trait/response class cheaper than taking a 0-dependent external dependency? (Honest answer: the glue code is the same either way; the package's real value is the curated problem catalogue and naming conventions.)
  4. Are we willing to own and maintain the Laravel adapter indefinitely, including when the upstream goes stale?
  5. Does the trace-in-debug payload conflict with our logging/PII policy, or with existing structured-log correlation IDs?

Integration Approach

Stack fit Good conceptual fit with Laravel's exception pipeline and renderable/reportable hooks, and with Laravel's existing JSON error output. It fits worst where Laravel has strong opinions: validation errors ({message, errors{}}), authentication redirects, and the default Handler shape. The package is not a drop-in replacement for Handler; it is a payload vocabulary consumed by it.

Migration path

  1. Land a first-party App\Support\Http\ProblemFactory + renderable behind a config flag (api.problem_details.enabled), defaulting off in production.
  2. Map core exceptions: ModelNotFoundException/NotFoundHttpException → NotFoundProblem, AuthenticationException → UnauthorizedProblem, AuthorizationException → ForbiddenProblem, ValidationException → custom validation problem (or ValidationApiProblem if we accept the Symfony dependency), ThrottleRequestsException → custom 429, ApiProblemException → passthrough.
  3. Publish the schema in OpenAPI (Problem component) and generate a contract test suite (JSON Schema assertions) that runs in CI against every error path.
  4. Enable in staging/internal consumers; dual-emit or version the envelope if external clients parse message/errors.
  5. Enable by default in production after a published deprecation window for the legacy shape.

Compatibility Requires PHP 8.x per recent releases — fine for Laravel 10/11/12 stacks. No Laravel version constraint exists because there is no Laravel coupling, so no framework-version lock risk; conversely, no upstream guarantee that our Laravel glue keeps working across majors — we own that. symfony/validator is an optional dependency only if we use ValidationApiProblem; avoiding it keeps the dependency tree clean.

Sequencing Contract decision (7807 vs 9457, field set incl. instance, traceId) → adapter + renderable → contract tests + OpenAPI → staging → external comms/versioning → production default. Estimate: 1 sprint for internal-only; 1–2 quarters if the envelope is a breaking public contract.

Operational Impact

Maintenance Very low code churn (small, stable surface, MIT, no transitive deps unless we opt into Symfony Validator). The real recurring cost is the Laravel adapter we write and the OpenAPI/contract test we maintain. Pin with a caret constraint and review at each PHP/Laravel major; a stale upstream is survivable because forking ~1,000 LOC of value objects is genuinely cheap.

Support No vendor support; GitHub issues only. Support burden lands on our platform team for both the package and the adapter. Developer ergonomics are strong (one-line throw), which reduces "how do I return an error?" churn in code review — a real, if soft, ROI.

Scaling Effectively zero runtime cost: pure value objects, no I/O, no caches, no bootstrapping. Negligible per-request allocation on error paths only. No scaling concern at any traffic level.

Failure modes to instrument

  • Wrong or missing Content-Type: application/problem+json (client parsers silently fall back).
  • Debug payload leaking trace/file/line into non-debug environments — enforce in config and add a test asserting the key is absent when app.debug=false.
  • Exceptions that bypass the renderable (fatal errors, abort() paths, queue/console contexts) returning the legacy shape, producing a two-format API.
  • Non-numeric or out-of-range exception codes — historically a bug source (fixed in 1.4.1/1.4.2); assert status is a valid 4xx/5xx int.
  • Validation payload divergence between Laravel's errors{} and RFC violations[], breaking existing client SDKs.
  • Consumers branching on title (human-readable, may change) rather than type (stable URI) — document that type is the contract.

Ramp-up Hours, not weeks: a mid-level Laravel developer can adopt the pattern in a single PR; the learning curve is the RFC vocabulary (type vs title vs detail, instance, about:blank), not the library. Budget one short internal doc/written standard so teams stop hand-rolling ad-hoc error arrays — that consistency is the primary product outcome this package buys us.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
dakiquang/laravel-oauth-refresh-lock
woda/laravel-worktrees
dalefranks/ramasite
faghy/laracashbook
roundly-consulting/google-places-for-laravel
roundly-consulting/kubernetes-api-for-laravel
roundly-consulting/plausible-for-laravel
gvp/gvp-laravel-template
metasyncsite/laravel-metasync-client
roundly-consulting/onboarding-for-laravel
andydefer/laravel-notification
adachsoft/cli-process-tester
jhaskell13/laraflow
sebastienheyd/boilerplate-media-manager
ccast/tagixo-primix
pretendtrue/laravel-builder
sawmainek/laravel-scout-tntsearch-driver
tomshaw/laravel-calendar-table
dibakar/laravel-ownership
adachsoft/changelog-linter