Renders consistent HTTP JSON responses for API-based projects

Overview

Laravel API Response Logo

GitHub Workflow Status Latest Version on Packagist License Total Downloads


Laravel API Response is a package that helps to provide and render a consistent HTTP JSON responses to API calls as well as converting and formatting exceptions to JSON responses.

Version Compatibility

Laravel Laravel API Response
9.x (Requires PHP >= 8.0) 1.x

Installation

You can install the package via composer:

composer require kennedy-osaze/laravel-api-response

You can publish the translation files using:

php artisan vendor:publish --tag="api-response-translations"

This will create a vendor folder (if it doesn't exists) in the lang folder of your project and inside, a api-response/en folder that has two files: errors.php and success.php. Both files are used for the translation of message strings in the JSON response sent out.

Optionally, you can publish the config file using:

php artisan vendor:publish --tag="api-response-config"

Usage

Using Package Traits

This package provides two traits that can be imported into your projects; namely:

  • The \KennedyOsaze\LaravelApiResponse\Concerns\RendersApiResponse trait which can be imported into your (base) controller class, middleware class or even your exception handler class
  • The \KennedyOsaze\LaravelApiResponse\Concerns\ConvertsExceptionToApiResponse trait which should only be imported into your exception handler class.

So we can have on the base controller class (from which all other controller may extend from):

<?php

namespace App\Http\Controllers;

use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
use KennedyOsaze\LaravelApiResponse\Concerns\RendersApiResponse;

class Controller extends BaseController
{
    use AuthorizesRequests, DispatchesJobs, ValidatesRequests, RendersApiResponse;
}

Or some random controller class:

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use KennedyOsaze\LaravelApiResponse\Concerns\RendersApiResponse;

class RandomController extends Controller
{
    use RendersApiResponse;
}

In any case, you have access to a load of methods which you can call to render your data. This includes:

// Successful Responses
return $this->okResponse('This is a random message', $data = null, $headers = []);
return $this->createdResponse('This is a random message', $data = null, $headers = []);
return $this->acceptedResponse($message, $data, $headers);
return $this->noContentResponse();
return $this->successResponse($message, $data = null, $status = 200, $headers = []);

// Successful Responses for \Illuminate\Http\Resources\Json\JsonResource
return $this->resourceResponse($jsonResource, $message, $status = 200, $headers = []);
return $this->resourceCollectionResponse($resourceCollection, $message, $wrap = true, $status = 200, $headers = []);

// Error Responses
return $this->unauthenticatedResponse('Unauthenticated message');
return $this->badRequestResponse('Bad request error message', $error = null);
return $this->forbiddenResponse($message);
return $this->notFoundResponse($message);
return $this->clientErrorResponse($message, $status = 400, $error = null, $headers = []);
return $this->serverErrorResponse($message);
return $this->validationFailedResponse($validator, $request = null, $message = null);

$messages = ['name' => 'Name is not valid'];
$this->throwValidationExceptionWhen($condition, $messages);

Also to handle exceptions, converting them to API response by using the \KennedyOsaze\LaravelApiResponse\Concerns\ConvertsExceptionToApiResponse trait in your exception handler which provides the renderApiResponse public method and this can be used as follows:

<?php

namespace App\Exceptions;

use App\Traits\HandleApiException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use KennedyOsaze\LaravelApiResponse\Concerns\ConvertsExceptionToApiResponse;
use Throwable;

class Handler extends ExceptionHandler
{
    use ConvertsExceptionToApiResponse;

    public function render($request, Throwable $e)
    {
        return $this->renderApiResponse($e, $request);
    }
}

You could also use the renderable method of the handler class:

<?php

namespace App\Exceptions;

use App\Traits\HandleApiException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use KennedyOsaze\LaravelApiResponse\Concerns\ConvertsExceptionToApiResponse;
use Throwable;

class Handler extends ExceptionHandler
{
    use ConvertsExceptionToApiResponse;

    public function register()
    {
        $this->renderable(function (Throwable $e, $request) {
            return $this->renderApiResponse($e, $request);
        });
    }
}

Using Package Classes

At the core of the above methods, there is an underlying ApiResponse class being called that can also be used as follows:

use KennedyOsaze\LaravelApiResponse\ApiResponse;

$response = new ApiResponse($status = 200, $message = 'Hello world', $data = ['age' => 20], $header = []);

return $response->make();

// Result
{
    "success": true,
    "message": "Hello world",
    "data": {
        'age' => 20
    }
}

// OR
return ApiResponse::create(400, 'Error occurred');

// Result
{
    "success": false,
    "message": "Error occurred"
}

// We could also have
$validator = Validator::make([], ['name' => 'required']);
return ApiResponse::fromFailedValidation($validator);

// Result
{
    "success": true,
    "message": "Validation Failed.",
    "errors": [
        "name": {
            "message": "The name field is required",
            "rejected_value": null
        }
    ]
}

// Also

$response = response()->json(['hello' => 'world']);

return ApiResponse::fromJsonResponse($response, $message = 'Hello');

// Result
{
    "success": true,
    "message": "hello"
    "data": {
        "hello": "world"
    }
}

If you would like to change the format for validation errors, you may call the registerValidationErrorFormatter static method of the ApiResponse class in the boot method of your App\Providers\AppServiceProvider class or any other service provider you want. You can do something like this:

<?php

// App\Providers\AppServiceProvider

use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Request;
use KennedyOsaze\LaravelApiResponse\ApiResponse;

public function boot()
{
    ApiResponse::registerValidationErrorFormatter(function (Validator $validator, Request $request) {
        return [
            'error_messages' => $validator->errors()->all(),
        ];
    });
}

Response Data

The response data $data to be rendered for successful response can be any of the following type:

  • array e.g. ['name' => 'Dummy']
  • standard object e.g. new stdClass
  • integer e.g. 1
  • boolean e.g. true
  • any Model object, instance of \Illuminate\Database\Eloquent\Model
  • any Collection object, instance of \Illuminate\Support\Collection
  • any JsonResource object, instance of \Illuminate\Http\Resources\Json\JsonResource
  • any Jsonable object, instance of \Illuminate\Contracts\Support\Jsonable
  • any JsonSerializable object, instance of \JsonSerializable
  • any Arrayable object, instance of \Illuminate\Contracts\Support\Arrayable

Any of the above can be used stored as $data and used thus:

use \KennedyOsaze\LaravelApiResponse\ApiResponse;

ApiResponse::create(200, 'A message', $data)

For API Resources JsonResources , you can create JSON responses by doing the following:

use App\Models\Book;
use App\Http\Resources\BookResource;
use App\Http\Resources\BookCollection;
use KennedyOsaze\LaravelApiResponse\ApiResponse;

$resource = new BookResource(Book::find(1));

return ApiResponse::fromJsonResponse($resource->response(), 'A book');

// Also

$collection = BookResource::collection(Book::all());

return ApiResponse:::fromJsonResponse($collection->response(), 'List of books');

// Also

$collection = new BookCollection(Book::paginate());

return ApiResponse::fromJsonResponse($collection->response, 'Paginated list of books')

Response Messages

This package uses translation files to translate messages defined when creating responses. This packages, as described earlier, comes with two translation files: success.php and errors.php. The success.php contains translations for success response messages while errors.php contains that of error response messages.

Given that you have a success.php translation file as thus:

<?php

return [
    'Account Created' => 'User account created successfully',
    'invoice_paid' => 'Invoice with number :invoice_number has been paid.',
];

The ApiResponse class would be able to translate messages as follows:

<?php

use KennedyOsaze\LaravelApiResponse\ApiResponse;

return ApiResponse::create(200, 'Account Created');

// Result
{
    "success": true,
    "message": "User account created successfully"
}

// Also:

return ApiResponse::create(200, 'invoice_paid:invoice_number=INV_12345');

// OR

return ApiResponse::create(200, 'invoice_paid', [
    '_attributes' => ['invoice_number' => 'INV_12345']
]);

// Result
{
    "success": true,
    "message": "Invoice with number INV_12345 has been paid."
}

// Also:

return ApiResponse::create(200, 'invoice_paid', [
    '_attributes' => ['invoice_number' => 'INV_12345'],
    'name' => 'Invoice for Mr Bean',
    'amount' => 1000,
    'number' => 'INV_12345'
]);

// Result
{
    "success": true,
    "message": "Invoice with number INV_12345 has been paid.",
    "data": {
        "name": "Invoice for Mr Bean",
        "amount": 1000,
        "number": "INV_12345"
    }
}

This is similar to how messages for error responses are translated except with the fact that the error messages are read from the errors.php translation file instead (or whatever you specify in the config file).

Also, for error messages, you can decide that error response should have error codes. You can provide error codes in your responses in a couple of ways:

<?php

use KennedyOsaze\LaravelApiResponse\ApiResponse;

return ApiResponse::create(400, 'Error message comes here.', [
    'error_code' => 'request_failed' // The error code here is "request_failed"
]);

// Result
{
    "success": false,
    "message": "Error message comes here.",
    "error_code": "request_failed"
}

Also, you can use the errors.php translation file to translate error codes. Given the below errors.php file:

return [

    'error_code' => [
        'example_code' => 'Just a failed error message',

        'error_code_name' => 'Example error message with status :status',
    ],
];

We can have a response with error code as follows:

<?php

use KennedyOsaze\LaravelApiResponse\ApiResponse;

return ApiResponse::create(400, 'error_code.example_code');

// Result

{
    "success": false,
    "message": "Just a failed error message",
    "error_code": "example_code"
}

// Also

return ApiResponse::create(400, 'error_code.error_code_name', [
    '_attributes' => ['status' => 'FAILED']
]);

// OR

return ApiResponse::create(400, 'error_code.error_code_name:status=FAILED');

// Result

{
    "success": false,
    "message": "Example error message with status FAILED",
    "error_code": "error_code_name"
}

Testing

composer test

Changelog

Please see CHANGELOG for more information on what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Security Vulnerabilities

If you discover any security related issues, please email [email protected] instead of using the issue tracker.

Credits

License

The MIT License (MIT). Please see License File for more information.

You might also like...
JSON-RPC 2.0 API server for @Laravel framework
JSON-RPC 2.0 API server for @Laravel framework

Sajya is an open-source project aiming to implement the JSON-RPC 2.0 server specification for the Laravel quickly.

JSON:API for Laravel applications

JSON:API for Web Artisans Implement feature-rich JSON:API compliant APIs in your Laravel applications. Build your next standards-compliant API today.

đź‘€ Manage your views in Laravel projects through artisan
đź‘€ Manage your views in Laravel projects through artisan

Artisan View This package adds a handful of view-related commands to Artisan in your Laravel project. Generate blade files that extend other views, sc

These projects are free for public use. Be a lesson for those who violate the rights of others!! ✌️

Faraz Kish Projects These projects are free for public use. Be a lesson for those who violate the rights of others!! ✌️ Brands Farazkish Uinvest MFina

A collection of helper functions that I use across my projects.

A collection of helper functions that I use across my projects. This package includes some of the helper functions that I tend to use in all of my pro

Useful blade components and functionality for most Laravel projects.

laravel-base Note: Package is still in early stages of development, so functionality is subject to change. LaravelBase is a package I've created to pr

Laravel-Mix helper for projects with complex & multi assets.
Laravel-Mix helper for projects with complex & multi assets.

Laravel-Mix helper for projects with complex & multi assets. 🔥 Getting started Since mix introduced in laravel 5.4 it is recommended to use this pack

Llum illuminates your Laravel projects speeding up your Github/Laravel development workflow
Llum illuminates your Laravel projects speeding up your Github/Laravel development workflow

Llum illuminates your Laravel projects speeding up your Github/Laravel development workflow

Quickly generate pivot tables for your projects
Quickly generate pivot tables for your projects

Laravel Pivot Table Generator Quickly generate pivot tables for your projects! Table of Contents Installation Usage More generator packages Contributi

Comments
Releases(1.2.1)
Owner
Kennedy Osaze
Kennedy Osaze
Builds nice, normalized and easy to consume REST JSON responses for Laravel powered APIs.

REST API Response Builder for Laravel Master branch: Development branch: Table of contents Introduction Why should I use it? Usage examples Features E

Marcin Orlowski 614 Dec 26, 2022
Flexihash is a small PHP library which implements consistent hashing.

Flexihash Flexihash is a small PHP library which implements consistent hashing, which is most useful in distributed caching. It requires PHP5 and uses

Paul Annesley 364 Oct 18, 2022
A lightweight package for handling API error responses.

Laravel API Errors This package provides an easy way to manage and handle error response for JSON API's. Installation You can install the package via

3 SIDED CUBE 2 Feb 9, 2022
Laravel Responder - a package for building API responses, integrating Fractal into Laravel and Lumen

A Laravel Fractal package for building API responses, giving you the power of Fractal with Laravel's elegancy.

Alexander Tømmerås 776 Dec 25, 2022
This package aims to help you standardize all your API responses in a simple and structured way.

Laravel API Response This package aims to help you standardize all your API responses in a simple and structured way. By default, the stucture of the

Kode Pandai 6 Dec 6, 2022
Caches responses as static files on disk for lightning fast page loads.

Laravel Page Cache This package allows you to easily cache responses as static files on disk for lightning fast page loads. Introduction Installation

Joseph Silber 1k Dec 16, 2022
Laravel Jsonable - Well-Formated Responses & Exceptions.

Laravel Jsonable Well-Formated Responses & Exceptions. Documentation You can find the detailed documentation here in Laravel Jsonable Documentation. C

Pharaonic 1 Aug 7, 2022
The fastest way to make a powerful JSON:API compatible Rest API with Laravel.

The first fully customizable Laravel JSON:API builder. "CRUD" and protect your resources with 0 (zero) extra line of code. Installation You can instal

BinarCode 288 Aug 8, 2022
Provides access to Pexels API for Laravel projects

Laravel Pexels Provides access to Pexels API for Laravel projects Table of contents Installation Using Installation To get the latest version of Larav

Raviga Group Limited 3 Dec 1, 2022
Lightweight JSON:API resource for Laravel

JSON:API Resource for Laravel A lightweight Laravel implementation of JSON:API. This is a WIP project currently being built out via livestream on my Y

Tim MacDonald 241 Jan 5, 2023