Simple package to handle response properly in your API.

Related tags

Laravel api-response
Overview

api-response

Latest Version Software License Api Response Tests Total Downloads

Simple package to handle response properly in your API. This package uses Fractal and is based on Build APIs You Won't Hate book.

Install

Via Composer

$ composer require ellipsesynergie/api-response

Requirements

The following versions of PHP are supported by this version:

>= PHP 7.4

Install in Laravel

Add this following service provider to your config/app.php file.

EllipseSynergie\ApiResponse\Laravel\ResponseServiceProvider::class

Install in Lumen

Because of the request object change (see reference) you can no longer access Request object properly in Service provider. To be convenient, we have created a middleware to be used for parsing the include parameter.

Register this service provider to your bootstrap/app.php file.

$app->register('EllipseSynergie\ApiResponse\Laravel\LumenServiceProvider');

Register the global middleware bootstrap/app.php file.

$app->middleware([
    'EllipseSynergie\ApiResponse\Laravel\Middleware\ParseInclude'
]);

Install in your favorite framework or vanilla php

This package can be used in any framework or vanilla php. You simply need to extend EllipseSynergie\ApiResponse\AbstractResponse and implement the withArray() method in your custom class. You can take a look at EllipseSynergie\ApiResponse\Laravel\Response::withArray() for an example.

You will also need to instantiate the response class with a fractal manager instance.

// Instantiate the fractal manager
$manager = new \League\Fractal\Manager;

// Set the request scope if you need embed data
$manager->parseIncludes(explode(',', $_GET['include']));

// Instantiate the response object, replace the class name by your custom class
$response = new \EllipseSynergie\ApiResponse\AbstractResponse($manager);

For more options related to the fractal manager, you can take a look at the official Fractal website

Example inside Laravel or Lumen controller



use EllipseSynergie\ApiResponse\Contracts\Response;

class BookController extends Controller {

    /**
     * @param Response $response
     */
    public function __construct(Response $response)
    {
        $this->response = $response;
    }

    /**
    * Example returning collection
    */
    public function index()
    {
        //Get all books
        $books = Book::all();
    
        // Return a collection of $books
        return $this->response->withCollection($books, new BookTransformer);
    }

    /**
    * Example returning collection with custom key
    */
    public function index()
    {
        //Get all books
        $books = Book::all();
        
        //Custom key
        $customKey = 'books';
    
        // Return a collection of books
        return $this->response->withCollection($books, new BookTransformer, $customKey);
    }

    /**
    * Example returning collection with paginator
    */
    public function index()
    {
        //Get all books
        $books = Book::paginate(15);
       
       // Return a collection of $books with pagination
       return $this->response->withPaginator(
           $books,
           new BookTransformer
       );
    }

    /**
    * Example returning collection with paginator with custom key and meta
    */
    public function index()
    {
        //Get all books
        $books = Book::paginate(15);
        
        //Custom key
        $customKey = 'books';
        
        //Custom meta
        $meta = [
            'category' => 'fantasy'
        ];
       
       // Return a collection of $books with pagination
       return $this->response->withPaginator(
           $books,
           new BookTransformer,
           $customKey,
           $meta
       );
    }

    /**
    * Example returning item
    */
    public function show($id)
    {
        //Get the book
        $book = Book::find($id);
    
        // Return a single book
        return $this->response->withItem($book, new BookTransformer);
    }

    /**
    * Example returning item with a custom key and meta
    */
    public function showWithCustomKeyAndMeta($id)
    {
        //Get the book
        $book = Book::find($id);
        
        //Custom key
        $customKey = 'book';
        
        //Custom meta
        $meta = [
            'readers' => $book->readers
        ];
    
        // Return a single book
        return $this->response->withItem($book, new BookTransformer, $customKey, $meta);
    }
    
    /**
    * Example resource not found
    */
    public function delete($id)
    {
        //Try to get the book
        $book = Book::find($id);

        //Book not found sorry !
        if(!$book){
            return $this->response->errorNotFound('Book Not Found');
        }
    }
    
    /**
    * Example method not implemented
    */
    public function whatAreYouTryingToDo()
    {
        return $this->response->errorMethodNotAllowed("Please don't try this again !");
    }
}

Ouput example

One book

{
    "data": {
        "id": 1,
        "title": "My name is Bob!.",
        "created_at": {
            "date": "2014-03-25 18:54:18",
            "timezone_type": 3,
            "timezone": "UTC"
        },
        "updated_at": {
            "date": "2014-03-25 18:54:18",
            "timezone_type": 3,
            "timezone": "UTC"
        },
        "deleted_at": null
    }
}

Collection of books

{
    "data": [
        {
           "id": 1,
           "title": "My name is Bob!",
           "created_at": {
               "date": "2014-03-25 18:54:18",
               "timezone_type": 3,
               "timezone": "UTC"
           },
           "updated_at": {
               "date": "2014-03-25 18:54:18",
               "timezone_type": 3,
               "timezone": "UTC"
           },
           "deleted_at": null
        },
        {
           "id": 2,
           "title": "Who's your dady ?",
           "created_at": {
               "date": "2014-03-26 18:54:18",
               "timezone_type": 3,
               "timezone": "UTC"
           },
           "updated_at": {
               "date": "2014-03-26 18:54:18",
               "timezone_type": 3,
               "timezone": "UTC"
           },
           "deleted_at": null
        }
    ]
}

Error

{
    "error": {
        "code": "GEN-NOT-FOUND",
        "http_code": 404,
        "message": "Book Not Found"
    }
}

Testing the package

$ phpunit

Testing within Laravel

According to the issue #31, we have found some problem when it's time to test the include query parameter value. If you want to resolve this issue in your test, you must use the trait EllipseSynergie\ApiResponse\Testing\Laravel\AddTestingSupportForInclude. To replace the call method from Illuminate\Foundation\Testing\Concerns\MakesHttpRequests::call

Contributing

Please see CONTRIBUTING for details.

Credits

License

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

Comments
  • Automated test responses don't include relationships

    Automated test responses don't include relationships

    In my application using this package (latest), I have an automated test that uses Laravel's (5.3 latest) built-in helpers to test a URL like this:

    $this->json('GET', "api/users/{$user->id}?include=posts");

    It is supposed to give me back a list of users with their posts. When I test the URL in postman or chrome, it works just fine. However, when I run the test on the command line (by running "phpunit") and dump-and-die the output, it just includes the user's information without the "posts" include.

    This is happening across the board for me in my automated tests for any endpoint that has a relationship. Based on what I've found by digging into Fractal and dump-and-dying all over the place, it looks like for some reason the "parseIncludes" function doesn't get set correctly when automated tests are run. But like I said, it's fine in a Postman test.

    To be honest, I can't tell for sure if this is Laravel's problem, Fractal's problem, or this packages problem. I am continuing to dig into it.

    opened by imjohnbon 9
  • IMPROVEMENT Add existing query params to pagination links

    IMPROVEMENT Add existing query params to pagination links

    This PR is to allow existing query params to be included within the pagination links.

    At present a call to /api/v1/search/?query=test will return /api/v1/search/?page=2 as the next link of the pagination links.

    This update will now set the next link to be /api/v1/search/?query=test&page=2 using the method outlined in the Fractal documentation.

    enhancement 
    opened by richdynamix 9
  • Does this handle exceptions?

    Does this handle exceptions?

    E.g. if I get an QueryException or a ModelNotFoundException will this library also give a json response? Or do I still need to make my own handler and in there return the errorNotFound etc. Thanks.

    question 
    opened by malhal 8
  • Server headers blocked

    Server headers blocked

    Hi, I would like to point out that, with error responses server defined headers are not sent. For example, in my case I use nginx with this configuration (only headers part) add_header X-Frame-Options SAMEORIGIN;
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";

    If I use errorNotFound() (or similar error-reporting methods) the headers are not present, both testing from local development server and from online virtual machine.

    opened by OxMarco 6
  • return json need $options

    return json need $options

    /**
         * @param array $array
         * @param array $headers
         * @return ResponseFactory
         */
        public function withArray(array $array, array $headers = [],$options = 0)
        {
            return response()->json($array, $this->statusCode, $headers,$options);
        }
    

    I need use $options as JSON_UNESCAPED_UNICODE can you add it ?

    enhancement 
    opened by dickwu 5
  • Changing customKey

    Changing customKey

    Hi,

    What is customKey for? Is customKey working?

    Cuz I try to set customKey to something else but it doesnt work

    Tried:

    return $this->response->withItem($newUser, new UserTransformer, 'user');
    

    and:

    return $this->response->withItem($newUser, new UserTransformer, ['key' => 'user']);
    ````
    
    
    opened by louisluu 4
  • Response::api() returns fatalErrorException

    Response::api() returns fatalErrorException

    When using Response::api() with any of the examples giving in the readme, the page throws the following error: Call to undefined method EllipseSynergie\ApiResponse\Laravel\Response::api()

    I have included this line in my controller use EllipseSynergie\ApiResponse\Laravel\Response; along with all the proper League\Fractal. When I use Fractal by itself everything works fine.

    opened by codivist 4
  • Added optional headers to all responses

    Added optional headers to all responses

    This allows optional headers to be passed with any response. Sometimes the response needs to include Auth tokens or additional headers, even with Error or Collection responses.

    opened by earnaway 3
  • Example of Response Class which does not include Laravel Response Factory

    Example of Response Class which does not include Laravel Response Factory

    Can you provide an example of what that withArray method needs to return on the response class? It looks like the Laravel Response class you reference in the docs, uses the Response Contract from Laravel5, but that has quite a bit of non-vanilla php within it. Here is what I have, but it's not returning anything currently

    use EllipseSynergie\ApiResponse\AbstractResponse as AbstractResponse;
    
    class ApiResponse extends AbstractResponse{
    
        /**
         * @param array $array
         * @param array $headers
         * @return ResponseFactory
         */
        public function withArray(array $array, array $headers = array())
        {
    
          return json_encode($array);
    
        }
    
    }
    
    opened by bryantAXS 3
  • Laravel 5 paginator class changed

    Laravel 5 paginator class changed

    Hi,

    Seems like the ->withPaginator() now receives a paginator of type Illuminate\Pagination\LengthAwarePaginator in L5 instead of the required Illuminate\Pagination\Paginator

    Is there a workaround?

    opened by etiennemarais 3
  • Make Transformer object optional

    Make Transformer object optional

    In some cases we just want to pass data without any transformer. Is it possible to make transformer object optional? like this Response::api()->withItem($data);

    opened by lidoma 3
  •  Call to undefined method Illuminate\Foundation\Application::middleware()

    Call to undefined method Illuminate\Foundation\Application::middleware()

    Steps to reproduce

    1. include the middleware in app/http/kernel.php

    Expected behaviour

    i expect the middleware to be registered as described in the readme

    Tell us what should happen

    Actual behaviour

    middleware not recognise

    Server configuration

    Operating system:

    **Web server:apache

    **Database:php

    **PHP version:7.2

    Client configuration

    **Browser:chrome

    **Operating system:windows

    Logs

    Web server error log

    
    Fatal error: Uncaught Error: Call to undefined method Illuminate\Foundation\Application::middleware() in C:\Users\SOLARSOFT\PhpstormProjects\lifetv\bootstrap\app.php:44
    Stack trace:
    #0 C:\Users\#####\PhpstormProjects\###\artisan(20): require_once()
    #1 {main}
      thrown in C:\Users\#########\PhpstormProjects\####\bootstrap\app.php on line 44
    
    
    
    opened by solarsoft0 1
  • Feature testing with ->get or ->json doesn't pass include string to Manager

    Feature testing with ->get or ->json doesn't pass include string to Manager

    Steps to reproduce

    1. When Testing endpoint, request a response with include $json = $this->actingAs($user, 'customer') ->json('GET','v2/customer', ['include'=>'cart']) ->assertJson([ 'data' => [ 'cart' => [ 'data' => [] ] ], ]);

    Expected behaviour

    Response should assert the 'cart' include, which works if I hit it with postman for example.

    Actual behaviour

    None of the includes, except the defaults are included

    duplicate 
    opened by jminkler 4
  • withCollection method gives bad json output. I can't convert it to array.

    withCollection method gives bad json output. I can't convert it to array.

    Steps to reproduce

    $this->response->withCollection( $users, new UserTransformer ); $array = json_decode($adminUserList);

    Expected behavior

    It should return an array

    Actual behavior

    It shows blank. I tested with json_last_error and showing error 4 which means bad syntax.

    Server configuration

    Ubuntu

    Apache

    Mysql

    PHP 7.0

    Client configuration

    Chrome

    opened by nileshlets 4
  • set includes for response

    set includes for response

    I wonder if there is a nicer way to set includes for the response. I dont mean to parse the includes from include parameter, but set them "manually" for that response.

    right now I am doing this (Laravel):

        $this->response->getManager()->parseIncludes('team');
        return $this->response->withItem($request->user(), new UserTransformer);
    

    Maybe something like

        return $this->response->parseIncludes('team')->withItem($request->user(), new UserTransformer);
    

    would be shorter and nicer. I could prepare a pull request if that's something you would like to integrate.

    opened by naabster 1
Releases(0.21.0)
Owner
Optania
Caring solutions, serving human beings
Optania
Simple and ready to use API response wrapper for Laravel.

Laravel API Response Simple Laravel API response wrapper. Installation Install the package through composer: $ composer require obiefy/api-response Re

Obay Hamed 155 Dec 14, 2022
A simple laravel package to handle multiple key based model route binding

Laravel Model UUID A simple package to handle the multiple key/column based route model binding for laravel package Installation Require the package u

null 13 Mar 2, 2022
This Package helps you in laravel application to log all desired activity for each request from request entry point to generate response at a single snapshot.

Laravel Scenario Logger This Package helps you in laravel application to log all desired activity for each request from request entry point to generat

Mehrdad Mahdian 6 Sep 27, 2021
Convert remote api response data into laravel model

laravel remote model Create remote driver to convert remote api request into laravel model. 中文文档 日本語文書 overview Install the version between laravel5.5

张子彬 15 Aug 11, 2022
Simple PSR-7 compatible response sender

Simple PSR-7 compatible response sender

Lazzard 4 Nov 5, 2022
Easily capture every incoming request and the corresponding outgoing response in your Laravel app.

Easily capture every incoming request and the corresponding outgoing response in your Laravel app. This package is designed to work only with the Lara

Mark Townsend 22 Nov 15, 2022
A laravel package to handle sanitize process of model data to create/update model records.

Laravel Model UUID A simple package to sanitize model data to create/update table records. Installation Require the package using composer: composer r

null 66 Sep 19, 2022
A laravel package to handle cascade delete and restore on model relations.

Laravel Model Soft Cascade A laravel package to handle cascade delete and restore on model relations. This package not only handle the cascade delete

Touhidur Rahman 18 Apr 29, 2022
A laravel package to handle model specific additional meta fields in an elegant way.

Laravel Meta Fields A php package for laravel framework to handle model meta data in a elegant way. Installation Require the package using composer: c

Touhidur Rahman 26 Apr 5, 2022
A package to handle the SEO in any Laravel application, big or small.

Never worry about SEO in Laravel again! Currently there aren't that many SEO-packages for Laravel and the available ones are quite complex to set up a

Ralph J. Smit 267 Jan 2, 2023
Laravel Soulbscription - This package provides a straightforward interface to handle subscriptions and features consumption.

About This package provides a straightforward interface to handle subscriptions and features consumption. Installation You can

Lucas Vinicius 269 Jan 1, 2023
A simple laravel state machine to handle model transitions, based on a pre-defined list of rules

A simple state machine that allows transitioning model states based on pre-defined rules. Installation You can install the package via composer: compo

Jack Mollart 18 Apr 2, 2022
A Laravel response helper methods.

A Laravel response helper methods. The package respond provides a fluent syntax to form array or json responses.

Najm Njeim 5 Nov 2, 2021
A Magento Incident Response Plan Template

A Magento centric Incident Response Plan Template Introduction This will provide you with our defined process and procedures to use when responding to

Talesh Seeparsan 75 Dec 30, 2022
Provides a powerful error response system for Laravel

Laravel Exceptions Laravel Exceptions was created by, and is maintained by Graham Campbell, and provides a powerful error response system for both dev

Graham Campbell 571 Jan 31, 2022
Laravel Custom Response Messages from Passport Oauth2 Server

This is a sample repository showing how to install Oauth2 server using Laravel's passport package and customize its responses.

M. Ismail 7 Nov 22, 2022
Laravel Response Formatter

I created this package to make it easier to format the response from a controller. I have used this package in my projects and I hope you enjoy it!

aris wahyudiyanto 12 Dec 5, 2022
Handle all the hard stuff related to EU MOSS tax/vat regulations, the way it should be.

VatCalculator Handle all the hard stuff related to EU MOSS tax/vat regulations, the way it should be. Integrates with Laravel and Cashier — or in a st

Dries Vints 1.1k Jan 5, 2023
Handle all the hard stuff related to EU MOSS tax/vat regulations, the way it should be.

VatCalculator Handle all the hard stuff related to EU MOSS tax/vat regulations, the way it should be. Integrates with Laravel and Cashier — or in a st

Dries Vints 1.1k Jan 7, 2023