raditzfarhan/laravel-api-response
Installation:
composer require raditzfarhan/laravel-api-response
No additional configuration or service provider registration is required (auto-discovered).
First Use Case:
Replace repetitive return response()->json() calls with the package’s fluent API. For example:
// In a controller
return response()->api()->success(['message' => 'User created']);
Output:
{
"success": true,
"message": "User created",
"data": null
}
Where to Look First:
success(), failed(), error()).Standard Responses:
// Success with data
return response()->api()->success($user);
// Failure with message
return response()->api()->failed('Invalid credentials');
// Error with HTTP code
return response()->api()->error('Unauthorized', 401);
Chaining for Complex Responses:
return response()->api()
->success()
->withMeta(['count' => 10])
->withLinks(['next' => url('/api/users?page=2')]);
Controller-Level Helper: Create a base controller to enforce consistent responses:
abstract class ApiController extends Controller {
protected function respondSuccess($data = null) {
return response()->api()->success($data);
}
}
Exception Handling: Use middleware to catch exceptions and return formatted errors:
// app/Http/Middleware/HandleApiErrors.php
public function handle($request, Closure $next) {
try {
return $next($request);
} catch (\App\Exceptions\ValidationException $e) {
return response()->api()->error($e->getMessage(), 400);
}
}
Facade for Global Access:
use Raditzfarhan\ApiResponse\Facades\ApiResponse;
// In a service or command
ApiResponse::success(['data' => 'global']);
ApiResource for structured data:
return response()->api()->success(new UserResource($user));
withMeta() to include pagination links:
return response()->api()
->success($users)
->withMeta(['pagination' => $users->links()]);
$response = $this->get('/api/users');
$response->assertJsonStructure([
'success',
'data',
'message',
'meta',
'links'
]);
Overriding Default Structure:
config('api-response') to inspect the current structure before modifying.Facade vs. Macro Conflicts:
response()->api() and ApiResponse::success() are used, ensure they return identical responses. The facade internally uses the macro, so conflicts are rare but possible if the macro is overridden.Nested Data Serialization:
->toArray() or ApiResource to flatten data.return response()->api()->success($user->load('posts')->toArray());
HTTP Status Codes:
200 for success and 400 for failures. Override explicitly for non-standard cases:
return response()->api()->success($data, 201); // Created
php artisan config:clear if responses appear malformed after config changes.\Log::debug((string) response()->api()->success($data));
dd(response()->api()->success()) to inspect the raw response object.Customize Response Structure: Publish the config and extend the default structure:
php artisan vendor:publish --provider="Raditzfarhan\ApiResponse\ApiResponseServiceProvider" --tag="config"
Then modify config/api-response.php:
'structure' => [
'success' => true,
'data' => null,
'errors' => null,
'meta' => null,
'links' => null,
'status_code' => 200,
],
Add Custom Methods:
Extend the ApiResponse class to add project-specific methods:
// app/Extensions/ApiResponseExtension.php
namespace App\Extensions;
use Raditzfarhan\ApiResponse\ApiResponse;
class ApiResponseExtension extends ApiResponse {
public function paginated($data) {
return $this->success($data)->withMeta(['pagination' => true]);
}
}
Register the extension in AppServiceProvider:
ApiResponse::macro('paginated', function () {
return (new ApiResponseExtension())->paginated(...func_get_args());
});
Performance:
->withoutWrapping() to skip the JSON wrapper for non-API routes (e.g., webhooks).Documentation:
/**
* @param mixed $data
* @return \Illuminate\Http\JsonResponse
*/
public function paginated($data) { ... }
Testing:
ApiResponse::shouldReceive('success')->once() in PHPUnit to test interactions:
ApiResponse::shouldReceive('success')
->once()
->with(['key' => 'value'])
->andReturnSelf();
How can I help you explore Laravel packages today?