Skip to content

Instantly share code, notes, and snippets.

@ahmadrosid
Last active October 5, 2019 03:33
Show Gist options
  • Save ahmadrosid/b2ee7437a60abb1365c0475488c3c4ff to your computer and use it in GitHub Desktop.
Save ahmadrosid/b2ee7437a60abb1365c0475488c3c4ff to your computer and use it in GitHub Desktop.
Json API adapter for lumen and laravel.

Installation

composer require league/fractal

Create folder app/Service and add file JsonApiAdapter.php and Transformer.php.

How to implement?

<?php


namespace App\Http\Controllers;

use App\Services\JsonApiAdapter;
use App\User;

class UserController
{
    public function index()
    {
        $users = User::paginate(5);

        return $this->adapter->setTransformer(new UserTransformer())
            ->setStatusCode(200)
            ->render($users);
    }

    public function show($id)
    {
        $user = User::find($id);

        return $this->adapter->setTransformer(new UserTransformer())
            ->setStatusCode(201)
            ->render($user);
    }
}

Sample Response

Response Single Item

{
    "data": {
        "type": "users",
        "id": "1",
        "attributes": {
            "name": "Mrs. Lila Swift II",
            "email": "jonatan.zieme@hotmail.com"
        },
        "links": {
            "self": "http://0.0.0.0:8000/users/1"
        }
    }
}

Response pagination

{
    "data": [
        {
            "type": "users",
            "id": "6",
            "attributes": {
                "name": "Mr. Tristian Padberg V",
                "email": "candida48@hotmail.com"
            },
            "links": {
                "self": "http://0.0.0.0:8000/users/6"
            }
        },
        {
            "type": "users",
            "id": "7",
            "attributes": {
                "name": "Miss Kaylee Toy",
                "email": "rzemlak@schneider.com"
            },
            "links": {
                "self": "http://0.0.0.0:8000/users/7"
            }
        },
        {
            "type": "users",
            "id": "8",
            "attributes": {
                "name": "Nils Dach",
                "email": "heidi.yundt@gmail.com"
            },
            "links": {
                "self": "http://0.0.0.0:8000/users/8"
            }
        },
        {
            "type": "users",
            "id": "9",
            "attributes": {
                "name": "Elmer Johnson III",
                "email": "wfeest@hotmail.com"
            },
            "links": {
                "self": "http://0.0.0.0:8000/users/9"
            }
        },
        {
            "type": "users",
            "id": "10",
            "attributes": {
                "name": "Rahsaan Hane IV",
                "email": "katlyn86@treutel.com"
            },
            "links": {
                "self": "http://0.0.0.0:8000/users/10"
            }
        }
    ],
    "meta": {
        "total": 50,
        "count": 5
    },
    "links": {
        "self": "http://0.0.0.0:8000/users?page=2",
        "first": "http://0.0.0.0:8000/users?page=1",
        "prev": "http://0.0.0.0:8000/users?page=1",
        "next": "http://0.0.0.0:8000/users?page=3",
        "last": "http://0.0.0.0:8000/users?page=10"
    }
}
<?php
namespace App\Services;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Arr;
use League\Fractal\Manager;
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use League\Fractal\Resource\Collection;
use League\Fractal\Resource\Item;
use League\Fractal\Serializer\JsonApiSerializer;
use League\Fractal\Serializer\SerializerAbstract;
use Exception;
class JsonApiAdapter
{
/**
* @var Transformer
*/
private $transformer;
/**
* @var string
*/
private $url;
/**
* @var Manager
*/
private $fractal;
/**
* @var int
*/
private $statusCode;
/**
* @var SerializerAbstract
*/
private $serializer;
/**
* JsonApiAdapter constructor.
* @param Manager $fractal
*/
public function __construct(Manager $fractal)
{
$this->url = url('/');
$this->fractal = $fractal;
}
/**
* @param Transformer $transformer
* @return $this
*/
public function setTransformer(Transformer $transformer)
{
$this->transformer = $transformer;
return $this;
}
/**
* @return string
*/
public function baseUrl()
{
return $this->url;
}
/**
* @param SerializerAbstract $serializer
* @return $this
*/
public function serialize(SerializerAbstract $serializer)
{
$this->serializer = $serializer;
return $this;
}
/**
* @param int $statusCode
* @return $this
*/
public function setStatusCode(int $statusCode)
{
$this->statusCode = $statusCode;
return $this;
}
/**
* @param $data
* @return \Illuminate\Http\JsonResponse
*/
public function render($data)
{
try {
$data = $this->serializeData($data);
} catch (Exception $e) {
$data = $e->getMessage();
}
return response()->json(
$data,
$this->statusCode
);
}
/**
* @param $data
* @return array
* @throws Exception
*/
private function serializeData($data)
{
if (null == $this->transformer){
throw new Exception("No transformer. Please et using setTransformer");
}
if (null == $this->serializer){
$this->serializer = new JsonApiSerializer($this->baseUrl());
}
$this->fractal->setSerializer($this->serializer);
if ($data instanceof LengthAwarePaginator){
$resource = new Collection($data, $this->transformer, $this->transformer->type);
$paginator = new IlluminatePaginatorAdapter($data);
$resource->setPaginator($paginator);
}else{
$resource = new Item($data, $this->transformer, $this->transformer->type);
}
$result = $this->fractal->createData($resource)->toArray();
if (isset($result['meta']['pagination'])){
$meta = Arr::only($result['meta']['pagination'], ['total', 'count']);
Arr::forget($result, 'meta.pagination');
Arr::set($result, 'meta', $meta);
}
return $result;
}
}
<?php
namespace App\Services;
use League\Fractal\TransformerAbstract;
abstract class Transformer extends TransformerAbstract
{
public $type;
public abstract function transform($model);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment