Skip to content

Remo/laravel5-jsonapi-transformer

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

51 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Laravel 5 JSON API Transformer Package

Scrutinizer Code Quality SensioLabsInsight Latest Stable Version Total Downloads License

Installation

Use Composer to install the package:

$ composer require nilportugues/laravel5-json-api

Laravel 5 / Lumen Configuration

Step 1: Add the Service Provider

Laravel

Open up config/app.php and add the following line under providers array:

'providers' => [

    //...
    NilPortugues\Laravel5\JsonApiSerializer\Laravel5JsonApiSerializerServiceProvider::class,
],

Lumen

Open up bootstrap/app.phpand add the following lines before the return $app; statement:

$app->register(\NilPortugues\Laravel5\JsonApiSerializer\Laravel5JsonApiSerializerServiceProvider::class);
$app->configure('jsonapi');

Also, enable Facades by uncommenting:

$app->withFacades();

Step 2: Add the mapping

Create a jsonapi.php file in config/ directory. This file should return an array returning all the class mappings.

Step 3: Usage

For instance, lets say the following object has been fetched from a Repository , lets say \App\Models\User - this being implemented in Eloquent, but can be anything.

This is its migration file:

<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateUsersTable extends Migration 
{

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('users', function(Blueprint $table)
        {
            $table->increments('id');
            $table->string('username', 30)->unique();
            $table->string('email')->unique();
            $table->string('password', 60);
            $table->integer('role_id')->unsigned();
            $table->boolean('seen')->default(false);
            $table->boolean('valid')->default(false);
            $table->boolean('confirmed')->default(false);
            $table->string('confirmation_code')->nullable();
            $table->timestamps();
            $table->rememberToken();            
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('users');
    }

}

And a series of mappings, placed in config/jsonapi.php, that require to use named routes so we can use the route() helper function:

<?php
//config/jsonapi.php
return [
    [
        'class' => '\App\Models\User',
        'alias' => 'User',
        'aliased_properties' => [
            'created_at' => 'registered_on',
        ],
        'hide_properties' => [
            'password', 
            'role_id',
            'seen', 
            'valid', 
            'confirmed', 
            'confirmation_code', 
            'remember_token',
            'updated_at'

        ],
        'id_properties' => [
            'id',
        ],
        'urls' => [
            'self' => 'get_user', //named route
        ],
        // (Optional)
        // 'relationships' => [
        //     'author' => [
        //         'related' => 'get_user_friends', //named route
        //         'self' => 'get_user_friends_relationship', //named route
        //     ]
        // ],
    ],
];

The named routes belong to the app/Http/routes.php. Here's a sample for the routes provided mapping:

Laravel

Route::get(
  '/user/{id}',
  ['as' => 'get_user', 'uses' => 'UserController@getOneUserAction']
);

Route::get(
  '/user',
  ['as' => 'get_users', 'uses' => 'UserController@getAllUsersAction']
);

//...

Lumen

$app->get(
  '/user/{id}',
  ['as' => 'get_user', 'uses' => 'UserController@getOneUserAction']
);

$app->get(
  '/user',
  ['as' => 'get_users', 'uses' => 'UserController@getAllUsersAction']
);

//...

All of this set up allows you to easily use the JsonApiSerializer service as follows:

<?php

namespace App\Http\Controllers;

use App\Models\User;
use NilPortugues\Laravel5\JsonApiSerializer\JsonApiSerializer;
use NilPortugues\Laravel5\JsonApiSerializer\JsonApiResponseTrait;

/**
 * Laravel Controller example
 */
class UserController extends \App\Http\Controllers\Controller
{
    use JsonApiResponseTrait;
    
    /**
     * @var App\Models\User
     */
    private $userRepository;

    /**
     * @var JsonApiSerializer
     */
    private $serializer;

    /**
     * @param User $userRepository
     * @param JsonApiSerializer $jsonApiSerializer
     */
    public function __construct(User $userRepository, JsonApiSerializer $jsonApiSerializer)
    {
        $this->userRepository = $userRepository;
        $this->serializer = $jsonApiSerializer;
    }

    /**
     * @param int $id
     *
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function getOneUserAction($id)
    {
        $user = $this->userRepository->find($id);
        
        /** @var \NilPortugues\Api\JsonApi\JsonApiTransformer $transformer */
        $transformer = $this->serializer->getTransformer();
        $transformer->setSelfUrl(route('get_user', ['id' => $id]));
        $transformer->setNextUrl(route('get_user', ['id' => $id+1]));

        return $this->response($this->serializer->serialize($user));
    }
    
    /**
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function getAllUsersAction()
    {
        return $this->response($this->serializer->serialize($this->userRepository->all()));
    }
}

Output:

This is the output for UserController@getAllUsersAction method:

HTTP/1.1 200 OK
Cache-Control: private, max-age=0, must-revalidate
Content-type: application/vnd.api+json
{
    "data": [
        {
            "type": "user",
            "id": "1",
            "attributes": {
                "username": "Admin",
                "email": "admin@example.com",
                "registered_on": "2015-09-07 18:02:18"
            },
            "links": {
                "self": {
                    "href": "http://localhost:8000/user/1"
                }
            }
        },
        {
            "type": "user",
            "id": "2",
            "attributes": {
                "username": "Redactor",
                "email": "redac@example.com",
                "registered_on": "2015-09-07 18:02:18"
            },
            "links": {
                "self": {
                    "href": "http://localhost:8000/user/2"
                }
            }
        },
        {
            "type": "user",
            "id": "3",
            "attributes": {
                "username": "Walker",
                "email": "walker@example.com",
                "registered_on": "2015-09-07 18:02:18"
            },
            "links": {
                "self": {
                    "href": "http://localhost:8000/user/3"
                }
            }
        },
    ],
    "jsonapi": {
        "version": "1.0"
    }
}

Request objects

JSON API comes with a helper Request class, NilPortugues\Api\JsonApi\Http\Message\Request(ServerRequestInterface $request), implementing the PSR-7 Request Interface. Using this request object will provide you access to all the interactions expected in a JSON API:

JSON API Query Parameters:
  • &filter[resource]=field1,field2
  • &include[resource]
  • &include[resource.field1]
  • &sort=field1,-field2
  • &sort=-field1,field2
  • &page[number]
  • &page[limit]
  • &page[cursor]
  • &page[offset]
  • &page[size]
NilPortugues\Api\JsonApi\Http\Message\Request

Given the query parameters listed above, Request implements helper methods that parse and return data already prepared.

namespace NilPortugues\Api\JsonApi\Http\Message;

final class Request
{
    public function __construct(ServerRequestInterface $request) { ... }
    public function getQueryParam($name, $default = null) { ... }
    public function getIncludedRelationships($baseRelationshipPath) { ... }
    public function getSortFields() { ... }
    public function getAttribute($name, $default = null) { ... }
    public function getSortDirection() { ... }
    public function getPageNumber() { ... }
    public function getPageLimit() { ... }
    public function getPageOffset() { ... }
    public function getPageSize() { ... }
    public function getPageCursor() { ... }
    public function getFilters() { ... }
}

Response objects (JsonApiResponseTrait)

The following JsonApiResponseTrait methods are provided to return the right headers and HTTP status codes are available:

    private function errorResponse($json);
    private function resourceCreatedResponse($json);
    private function resourceDeletedResponse($json);
    private function resourceNotFoundResponse($json);
    private function resourcePatchErrorResponse($json);
    private function resourcePostErrorResponse($json);
    private function resourceProcessingResponse($json);
    private function resourceUpdatedResponse($json);
    private function response($json);
    private function unsupportedActionResponse($json);

Quality

To run the PHPUnit tests at the command line, go to the tests directory and issue phpunit.

This library attempts to comply with PSR-1, PSR-2, PSR-4 and PSR-7.

If you notice compliance oversights, please send a patch via Pull Request.


## Contribute

Contributions to the package are always welcome!


## Support

Get in touch with me using one of the following means:


## Authors

License

The code base is licensed under the MIT license.

About

Laravel 5 JSON API Transformer Package

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • PHP 100.0%