Simple package to handle response properly in your API. This package uses Fractal and is based on Build APIs You Won't Hate book.
Via Composer
$ composer require ellipsesynergie/api-response
The following versions of PHP are supported by this version:
>= PHP 8.1
Add this following service provider to your config/app.php
file.
EllipseSynergie\ApiResponse\Laravel\ResponseServiceProvider::class
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'
]);
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
<?php
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 !");
}
}
{
"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
}
}
{
"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": {
"code": "GEN-NOT-FOUND",
"http_code": 404,
"message": "Book Not Found"
}
}
$ phpunit
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
Please see CONTRIBUTING for details.
The MIT License (MIT). Please see License File for more information.