curly-deni / laravel-api-concern
Reusable API responses and exception rendering for Laravel
Requires
- php: ^8.4
- laravel/framework: ^11.0||^12.0||^13.0
Requires (Dev)
- larastan/larastan: ^3.0
- laravel/pint: ^1.14
- nunomaduro/collision: ^8.8
- orchestra/testbench: ^11.0.0||^10.0.0||^9.0.0
- pestphp/pest: ^4.0
- pestphp/pest-plugin-laravel: ^4.0
- phpstan/extension-installer: ^1.4
- phpstan/phpstan-deprecation-rules: ^2.0
- phpstan/phpstan-phpunit: ^2.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Reusable JSON response helpers and API exception rendering for Laravel 11, 12, and 13.
Installation
composer require curly-deni/laravel-api-concern
Laravel auto-discovers the service provider. It registers the package's English and Russian translations. To customize them, publish the translation files:
php artisan vendor:publish --tag=api-concern-translations
Published translations are placed in lang/vendor/api-concern and override the package defaults.
Responses
Use HasApiResponses in a controller to return the standard response envelopes:
use Aesis\ApiConcern\Concerns\HasApiResponses; use Illuminate\Routing\Controller; class UserController extends Controller { use HasApiResponses; public function store() { return $this->created(['id' => 1], ['request_id' => 'abc']); } }
Available helpers are data, created, accepted, noContent, resource, createdResource, acceptedResource, and error. Data responses use a data key and include meta only when provided. Error responses use an error object containing code, message, and optional details.
You can also inject Aesis\ApiConcern\Http\ApiResponseFactory directly.
Exception rendering
Add the renderer to the existing withExceptions callback in bootstrap/app.php. Keep the path check in the application so web exceptions continue through Laravel's normal handling:
use Aesis\ApiConcern\Http\ApiExceptionRenderer; use Illuminate\Foundation\Configuration\Exceptions; use Illuminate\Http\Request; use Throwable; ->withExceptions(function (Exceptions $exceptions): void { $exceptions->render(function (Throwable $exception, Request $request) { if (! $request->is('api/v1/*')) { return null; } return app(ApiExceptionRenderer::class)->render($exception); }); })
For matching requests, the renderer converts validation, authentication, authorization, missing model, throttling, HTTP, and unexpected exceptions to a consistent JSON shape. Throw Aesis\ApiConcern\Exceptions\ApiException for an application-specific error:
throw new ApiException('account_locked', 'This account is locked.', 423, ['retry_after' => 60]);
Translations
The renderer uses Laravel's api-concern::messages.* translation keys. English and Russian defaults are included. Set the application's locale to choose a language, or publish the files and edit them for application-specific wording.
Testing
composer test
composer analyse
composer format
License
MIT. See LICENSE.md.