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

Laravel Api Response Laravel Package

kodepandai/laravel-api-response

A Laravel package for building consistent API responses with simple helpers for success, error, validation, and paginated JSON output. It standardizes response structure, status codes, and messages so your APIs stay clean and predictable.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and confirm wiring. composer require kodepandai/laravel-api-response and let Laravel's package discovery register the service provider. If the package ships a config file, publish it (php artisan vendor:publish --tag=...) and commit it so response envelopes stay stable across environments.

Look here first, in order:

  1. The published config (default response structure, status codes, and any debug/exception toggles).
  2. The ApiResponse class/factory — this is the shape every controller returns.
  3. The package's ExceptionHandler — since v1.3.1 this correctly converts an ApiResponse into a JsonResponse, which is the piece you'll touch when customising error rendering.

Register the exception handler per the README (in Laravel 10 and below via App\Exceptions\Handler::register(), in Laravel 11+ inside bootstrap/app.php's withExceptions(...)). This is the step most likely to be skipped — the package works for happy-path responses without it, but errors will fall back to Laravel's default rendering.

First use case: a single GET /api/v1/ping returning a success envelope, plus a route that throws a ModelNotFoundException, to verify both the success path and the exception path render identically. Confirm with curl -H "Accept: application/json" so you see the JSON branch, not the HTML error page.

Implementation Patterns

Trait on a base controller. Put the package trait (or a thin wrapper of your own) on App\Http\Controllers\Controller and expose helpers like success()/error() to every child controller. Wrapping the package rather than calling it directly everywhere gives you one place to change the envelope later.

Throw, don't return, for errors. The v1.3.1 fix targets exactly this: your exception handler returns an ApiResponse, and the package now converts it to a JsonResponse instead of leaking a PSR-7/plain object. The clean pattern is domain exceptions (InsufficientFundsException) thrown from services, mapped to status codes and messages in the handler, with controllers staying free of error-formatting code.

Uniform error mapping table. Keep a single match/array mapping exception class → HTTP status → error code in the handler. Add entries as domain exceptions appear; avoid per-controller try/catch that builds its own payloads, or you'll drift from the envelope.

Resources and pagination. Return Eloquent API Resources inside the success helper (pass Resource::collection(...) as the data), not the other way round. For paginators, pass the paginator itself so meta (current page, total, per-page) is derivable, and keep data/meta/links split consistent across endpoints.

Form requests carry validation. Validation failures arrive as ValidationException; let the handler render them through the same envelope (typically 422 with an errors key) rather than overriding failedValidation() per request.

Version your envelope deliberately. If you namespace routes under /api/v1, snapshot a couple of JSON fixtures in tests and assert against them; envelope changes are the easiest breaking change to ship by accident.

Testing hooks. Assert on assertJsonStructure(['data', 'message', ...]) rather than exact payloads, and use $this->withoutExceptionHandling() in a separate test class to assert the raw exception type when you need to test service logic.

Gotchas and Tips

  • Upgrade v1.3.1 if you return ApiResponse from render()/report(). Before this fix, a custom handler returning the package response object produced a broken or non-JSON response — symptoms are HTML error pages, empty bodies, or "the response is not JSON" from clients. If you worked around it by hand-building response()->json($apiResponse->toArray(), $code), you can likely delete that shim.
  • Handler ordering matters. Laravel resolves render() callbacks top-down; a broad Throwable/Exception catch-all registered early will swallow the package's handling. Register specific exceptions first.
  • PHP 8.2 support is now explicit. The package's constraints are tested on 8.2, so on a modern Laravel you can rely on it in CI without --ignore-platform-reqs. If you're still on 8.0, pin carefully — the new constraint may have moved the minimum.
  • Status code lived in two places. The HTTP status and the in-body code are separate; set both from one mapping or clients that branch on the body will disagree with the transport.
  • Accept header is a real dependency. Browsers and some HTTP clients omit application/json, so exception rendering diverges between environments. Force JSON for API routes via middleware or a route-group default.
  • Config caching. After changing the published config, run php artisan config:clear; in Octane/FrankenPHP workers, restart the workers or you'll chase a stale envelope.
  • Don't double-wrap. Passing an already-wrapped ApiResponse (or a JsonResponse) into a helper typically nests it under data. Assert the top-level keys in a test to catch this early.
  • Debugging tip: temporarily log inside your handler's render()/report() and dump get_class($e) — most "the handler isn't working" reports are a handler that was never reached because the route sat outside the relevant middleware group or withExceptions wiring.
  • Extension points: use a custom exception renderer registered in the handler for per-exception payloads, and a small ApiResponse subclass or macro if you need extra meta keys — preferable to post-processing arrays in controllers.
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.
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator