Keeping your API response consistent in the project helps developers with easier to work with the API and have the same expectation over the response whether the error or successful response. In Laravel to centralize the API responses, you can use the PHP trait. As php.net, “trait is a mechanism for code reuse in a single inheritance language such as PHP. A Trait is intended to reduce some limitations of single inheritance by enabling a developer to reuse sets of methods freely in several independent classes living in different class hierarchies.”
Create APIResponseTrait
In the root of your Laravel project create a trait as below.
In the ./app/Traits/APIResponseTrait.php
<?php
namespace App\Traits;
use Illuminate\Http\Response;
trait APIResponseTrait
{
/**
* Building success response
* @param $data
* @param int $code
* @return JsonResponse
*/
public function successResponse($response = null)
{
if ($response instanceof \App\Http\Resources\APIPaginateCollection) {
return response()->json($response, Response::HTTP_OK);
}
if ($response) {
return response()->json(['data' => $response], Response::HTTP_OK);
}
return response()->json(['data' => [
'success' => true
]], Response::HTTP_OK);
}
/**
* Building success response
* @param $data
* @param int $code
* @return JsonResponse
*/
public function errorResponse($exception, $statusCode = Response::HTTP_NOT_FOUND)
{
return response()->json([
'data' => [
'success' => false,
'message' => $exception->getMessage()
]
], $statusCode);
}
}
Integrate trait to the controller
In the ./app/Http/Controllers/Controller.php
Add the use APIResponseTrait
<?php
namespace App\Http\Controllers;
use App\Traits\APIResponseTrait;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests, APIResponseTrait;
}
Usage
In any class that inherits from the controller, you can call the response function.
This is the sample usage.
<?php
namespace App\Http\Controllers;
use App\Http\Requests\ProductImportRequest;
use App\Http\Requests\ProductRequest;
use App\Http\Resources\APIPaginateCollection;
use App\Http\Resources\ProductResource;
use App\Models\Product;
use Illuminate\Http\Request;
class ProductController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
{
try {
$perPage = $request->per_page ? $request->per_page : 10;
$currentPage = $request->current_page ? $request->current_page : 1;
$products = Product::paginate($perPage, ["*"], "page", $currentPage);
$response = new APIPaginateCollection($products, ProductResource::class);
return $this->successResponse($response);
} catch (\Throwable $th) {
return $this->errorResponse($th);
}
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(ProductRequest $request)
{
try {
Product::create($request->only("name", "price"));
return $this->successResponse();
} catch (\Throwable $th) {
return $this->errorResponse($th);
}
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
try {
$product = Product::findOrFail($id);
$response = new ProductResource($product);
return $this->successResponse($response);
} catch (\Throwable $th) {
return $this->errorResponse($th);
}
}
}