anyo-lab / api-response
A Laravel package for universal API response and error handling
Installs: 5
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/anyo-lab/api-response
Requires
- php: ^8.1
- illuminate/cache: ^9.0|^10.0|^11.0|^12.0
- illuminate/http: ^9.0|^10.0|^11.0|^12.0
- illuminate/support: ^9.0|^10.0|^11.0|^12.0
- illuminate/validation: ^9.0|^10.0|^11.0|^12.0
Requires (Dev)
- laravel/pint: ^1.0
- orchestra/testbench: ^7.0|^8.0|^9.0
- phpstan/phpstan: ^2.0
- phpunit/phpunit: ^9.0|^10.0
This package is not auto-updated.
Last update: 2026-02-24 16:02:27 UTC
README
A comprehensive Laravel package for universal API response and error handling. This package provides a standardized way to format API responses and handle exceptions in Laravel applications with multiple usage patterns and advanced features.
π Features
- π― Standardized API Responses - Consistent response format across your entire API
- π‘οΈ Automatic Exception Handling - Custom exception handler for API routes
- π Multiple Usage Methods - Use as service, trait, facade, macros, or helper functions
- βοΈ Highly Configurable - Customize response structure and messages
- π Built-in Pagination - Automatic pagination response formatting
- π§ Laravel 9-12 Support - Compatible with multiple Laravel versions
- π― Resource Classes - Built-in resource transformation classes
- π Response Macros - Extend Laravel's response with API methods
- π Global Helpers - Easy-to-use global helper functions
- π οΈ Middleware Support - Automatic response formatting middleware
- π¦ Rate Limiting Integration - Formatted rate limiting responses
- π¦ Response Compression - Automatic response compression (gzip, deflate)
- π API Versioning - Built-in API versioning support
- π Performance Monitoring - Response performance tracking
π Requirements
- PHP >= 8.1
- Laravel >= 9.0
π§ Installation
Via Composer
composer require anyo-lab/api-response
Manual Installation
- Clone or download this package
- Add to your
composer.json:
{
"require": {
"anyo-lab/api-response": "*"
},
"repositories": [
{
"type": "path",
"url": "path/to/api-response"
}
]
}
- Run
composer update
βοΈ Configuration
Publish the configuration file:
php artisan vendor:publish --provider="ApiResponse\ApiResponseServiceProvider" --tag="api-response-config"
This will create config/api-response.php with customizable options.
Production readiness
Before using in a live project:
- Set
APP_DEBUG=falsein.envso error responses never expose stack traces or file paths. - Publish config (optional):
php artisan vendor:publish --tag=api-response-configto override messages, structure, or timestamp format. - Override messages in
config/api-response.phpundermessagesso all default strings (e.g. "Resource not found") come from one place. - Optional: Enable
include_request_idandinclude_error_codesin config for tracing and machine-readable error codes.
All responses use the same config (structure, timestamp, error codes). ResponseHelper and resources use the same settings as the main ApiResponse service.
Upgrading / Breaking changes
-
Response caching removed: The package no longer provides
api_cache(),api_remember(), orApiResponseCache. For cached API responses, use LaravelβsCache::remember()withapi_success():use Illuminate\Support\Facades\Cache; $data = Cache::remember('users.list', 3600, fn () => User::all()); return api_success($data, 'Success');
-
204 No Content:
noContent()now returns an empty response body (RFC 7231) instead of a JSON body. -
Performance monitoring optional: Set
register_performance_monitoringtofalsein config to disable cache usage when you do not useapi_performance().
See CHANGELOG.md for full version history.
π― Quick Start
Basic Usage
use ApiResponse\ApiResponse; class UserController extends Controller { public function index(ApiResponse $apiResponse) { $users = User::paginate(10); return $apiResponse->paginated($users, 'Users retrieved successfully'); } public function store(Request $request, ApiResponse $apiResponse) { $user = User::create($request->validated()); return $apiResponse->created($user, 'User created successfully'); } }
Tip: For testability and flexibility, type-hint ApiResponseContract instead of ApiResponse so you can swap or mock the implementation.
π Usage Methods
Method 1: Service Injection
use ApiResponse\ApiResponse; class UserController extends Controller { public function index(ApiResponse $apiResponse) { $users = User::paginate(10); return $apiResponse->paginated($users, 'Users retrieved successfully'); } public function store(Request $request, ApiResponse $apiResponse) { $user = User::create($request->validated()); return $apiResponse->created($user, 'User created successfully'); } }
Method 2: Trait Usage
use ApiResponse\Traits\ApiResponseTrait; class UserController extends Controller { use ApiResponseTrait; public function index() { $users = User::paginate(10); return $this->paginatedResponse($users, 'Users retrieved successfully'); } public function store(Request $request) { $user = User::create($request->validated()); return $this->createdResponse($user, 'User created successfully'); } }
Method 3: Facade Usage
use ApiResponse\Facades\ApiResponse; class UserController extends Controller { public function index() { $users = User::paginate(10); return ApiResponse::paginated($users, 'Users retrieved successfully'); } public function store(Request $request) { $user = User::create($request->validated()); return ApiResponse::created($user, 'User created successfully'); } }
Method 4: Response Macros
class UserController extends Controller { public function index() { $users = User::paginate(10); return response()->apiPaginated($users, 'Users retrieved successfully'); } public function store(Request $request) { $user = User::create($request->validated()); return response()->apiCreated($user, 'User created successfully'); } }
Method 5: Global Helper Functions
class UserController extends Controller { public function index() { $users = User::paginate(10); return api_paginated($users, 'Users retrieved successfully'); } public function store(Request $request) { $user = User::create($request->validated()); return api_created($user, 'User created successfully'); } }
Method 6: Resource Classes
use ApiResponse\Resources\ApiResource; use Illuminate\Http\Request; class UserResource extends ApiResource { protected function transformData(Request $request): array { return [ 'id' => $this->id, 'name' => $this->name, 'email' => $this->email, 'created_at' => $this->created_at?->toISOString(), ]; } protected function getMessage(): string { return 'User retrieved successfully'; } } class UserController extends Controller { public function show($id) { $user = User::findOrFail($id); return new UserResource($user); } public function index() { $users = User::paginate(10); return UserResource::collection($users); } }
π€ Response Methods
Success Responses
// Basic success response $apiResponse->success($data, 'Success message'); // Created response (201) $apiResponse->created($data, 'Resource created'); // No content response (204) $apiResponse->noContent('No content available'); // Paginated response $apiResponse->paginated($paginator, 'Data retrieved'); // Collection response $apiResponse->collection($collection, 'Data retrieved'); // Resource response $apiResponse->resource($resource, 'Resource retrieved');
Error Responses
// Basic error response $apiResponse->error('Error message', 400); // Validation error (422) $apiResponse->validationError($errors, 'Validation failed'); // Not found (404) $apiResponse->notFound('Resource not found'); // Unauthorized (401) $apiResponse->unauthorized('Authentication required'); // Forbidden (403) $apiResponse->forbidden('Access denied'); // Server error (500) $apiResponse->serverError('Internal server error'); // Bad request (400) $apiResponse->badRequest('Invalid request'); // Conflict (409) $apiResponse->conflict('Resource conflict'); // Too many requests (429) $apiResponse->tooManyRequests('Rate limit exceeded');
π Response Format
All responses follow this standardized format:
Success Response
{
"success": true,
"message": "Success message",
"data": {
"id": 1,
"name": "John Doe",
"email": "john@example.com"
},
"errors": null,
"meta": null,
"timestamp": "2024-01-01T12:00:00.000000Z"
}
Error Response
{
"success": false,
"message": "Error message",
"data": null,
"errors": {
"email": ["The email field is required."],
"password": ["The password must be at least 8 characters."]
},
"meta": null,
"timestamp": "2024-01-01T12:00:00.000000Z"
}
Pagination Response
{
"success": true,
"message": "Data retrieved successfully",
"data": [
{
"id": 1,
"name": "John Doe"
}
],
"errors": null,
"meta": {
"current_page": 1,
"per_page": 10,
"total": 100,
"last_page": 10,
"from": 1,
"to": 10,
"has_more_pages": true
},
"timestamp": "2024-01-01T12:00:00.000000Z"
}
π‘οΈ Exception Handling
The package includes a custom exception handler that automatically formats exceptions for API routes:
| Exception | Status Code | Description |
|---|---|---|
ValidationException |
422 | Validation errors |
AuthenticationException |
401 | Unauthorized |
ModelNotFoundException |
404 | Not found |
NotFoundHttpException |
404 | Not found |
QueryException |
500 | Server error (with debug info in development) |
HttpException |
Respective | HTTP status code |
βοΈ Configuration Options
Response Structure
'structure' => [ 'success' => 'success', 'message' => 'message', 'data' => 'data', 'errors' => 'errors', 'meta' => 'meta', 'timestamp' => 'timestamp', ],
Default Messages
'messages' => [ 'success' => 'Success', 'created' => 'Resource created successfully', 'updated' => 'Resource updated successfully', 'deleted' => 'Resource deleted successfully', 'not_found' => 'Resource not found', 'unauthorized' => 'Unauthorized', 'forbidden' => 'Forbidden', 'validation_failed' => 'Validation failed', 'server_error' => 'Internal server error', 'bad_request' => 'Bad request', 'conflict' => 'Conflict occurred', 'too_many_requests' => 'Too many requests', ],
Other Options
'include_timestamp' => true, 'timestamp_format' => 'Y-m-d H:i:s', 'debug' => env('APP_DEBUG', false), 'use_exception_handler' => true, 'api_routes_pattern' => 'api/*',
π Advanced Features
Middleware Support
// In your routes/api.php Route::middleware(['api.response'])->group(function () { Route::get('/users', [UserController::class, 'index']); Route::post('/users', [UserController::class, 'store']); }); // Or register globally in App\Http\Kernel.php protected $middlewareGroups = [ 'api' => [ \ApiResponse\Http\Middleware\ApiResponseMiddleware::class, // ... other middleware ], ];
API Versioning
use ApiResponse\Services\ApiVersioningService; class UserController extends Controller { public function index(ApiVersioningService $versioning) { $version = $versioning->getVersion(request()); if ($version === 'v2') { // Return v2 format return $this->paginatedResponseV2($users); } // Return v1 format return $this->paginatedResponse($users); } }
Response Compression
use ApiResponse\Services\ResponseCompressionService; class UserController extends Controller { public function index(ResponseCompressionService $compression) { $response = $this->paginatedResponse($users); return $compression->compress(request(), $response); } }
Performance Monitoring
use ApiResponse\Services\PerformanceMonitoringService; class UserController extends Controller { public function index(PerformanceMonitoringService $monitoring) { $monitoring->startMonitoring(request()); $users = User::paginate(10); $response = $this->paginatedResponse($users); $monitoring->endMonitoring(request(), $response); return $response; } }
π§ͺ Testing
<?php namespace Tests\Feature; use Tests\TestCase; use App\Models\User; class UserApiTest extends TestCase { public function test_can_get_users() { $response = $this->getJson('/api/users'); $response->assertStatus(200) ->assertJsonStructure([ 'success', 'message', 'data', 'meta', 'timestamp' ]) ->assertJson([ 'success' => true, 'message' => 'Users retrieved successfully' ]); } public function test_can_create_user() { $userData = [ 'name' => 'John Doe', 'email' => 'john@example.com', 'password' => 'password123' ]; $response = $this->postJson('/api/users', $userData); $response->assertStatus(201) ->assertJson([ 'success' => true, 'message' => 'User created successfully' ]); } public function test_validation_errors() { $response = $this->postJson('/api/users', []); $response->assertStatus(422) ->assertJson([ 'success' => false, 'message' => 'Validation failed' ]) ->assertJsonStructure([ 'errors' => [ 'name', 'email', 'password' ] ]); } }
π Complete Example
<?php namespace App\Http\Controllers; use App\Models\User; use Illuminate\Http\Request; use ApiResponse\Traits\ApiResponseTrait; use Illuminate\Validation\ValidationException; use Illuminate\Database\Eloquent\ModelNotFoundException; class UserController extends Controller { use ApiResponseTrait; public function index() { try { $users = User::paginate(10); return $this->paginatedResponse($users, 'Users retrieved successfully'); } catch (\Exception $e) { return $this->serverErrorResponse('Failed to retrieve users'); } } public function store(Request $request) { try { $validated = $request->validate([ 'name' => 'required|string|max:255', 'email' => 'required|email|unique:users', 'password' => 'required|min:8', ]); $user = User::create($validated); return $this->createdResponse($user, 'User created successfully'); } catch (ValidationException $e) { return $this->validationErrorResponse($e->errors(), 'Validation failed'); } catch (\Exception $e) { return $this->serverErrorResponse('Failed to create user'); } } public function show($id) { try { $user = User::findOrFail($id); return $this->resourceResponse($user, 'User retrieved successfully'); } catch (ModelNotFoundException $e) { return $this->notFoundResponse('User not found'); } } public function update(Request $request, $id) { try { $user = User::findOrFail($id); $validated = $request->validate([ 'name' => 'sometimes|string|max:255', 'email' => 'sometimes|email|unique:users,email,' . $id, ]); $user->update($validated); return $this->successResponse($user, 'User updated successfully'); } catch (ModelNotFoundException $e) { return $this->notFoundResponse('User not found'); } catch (ValidationException $e) { return $this->validationErrorResponse($e->errors(), 'Validation failed'); } } public function destroy($id) { try { $user = User::findOrFail($id); $user->delete(); return $this->successResponse(null, 'User deleted successfully'); } catch (ModelNotFoundException $e) { return $this->notFoundResponse('User not found'); } } }
Testing this package
composer install composer test # run PHPUnit composer format:check # Laravel Pint composer analyse # PHPStan
Enterprise & production
For production use, enable request IDs and error codes in config; apply rate limiting and set APP_DEBUG=false.
π€ Contributing
Please see CONTRIBUTING.md for development setup, code style, and pull request guidelines.
Security
If you discover a security vulnerability, please see SECURITY.md.
Changelog
See CHANGELOG.md for version history.
π License
This package is open-sourced software licensed under the MIT license.
π Support
- Issues: GitHub Issues
- Documentation: Full Documentation
π Acknowledgments
- Laravel team for the amazing framework
- All contributors who help improve this package
- The open-source community for inspiration and feedback
Laravel API Response β A generic package for standardized API responses.