ratiw/api

A simple Laravel API package.

dev-master 2015-02-13 04:26 UTC

This package is not auto-updated.

Last update: 2024-04-23 02:00:49 UTC


README

A simple Laravel based API package using Fractal. At the moment, Laravel 5 is not yet officially released, so this package was based on Laravel 4.2.

This package simplify the API request building and transforming using The PHP Leagues's Fractal as the underlying engine.

To use it, you just need to follow these 3 steps

  • Create API endpoint by extending the Ratiw\Api\BaseApiController class.
  • Create Transformer by extending Ratiw\Api\BaseTransformer class.
  • Create a route for it.

Installation

Installation can be done via composer

"require": {
    "ratiw/api": "dev-master"
}

This package requires Laravel Framework v4.2 and Fractal v0.9.*, so it will be pull in automatically

Usage

####Let's make the assumptions

  • The API code will be in Api directory.
  • The following PSR-4 namespaces were defined in composer.json like so
	...
	"autoload": {
		"psr-4": {
			"Api\\": "app/Api",
			"Entities\\": "app/Entities"
		}
	}
	...
  • The API classes will be put in Api\Controllers directory.
  • The Transformer classes will be put in Api\Transformers directory.
  • A simple Client eloquent based class exists in the `Entities\Clients' directory.
<?php namespace Entities\Clients;

class Client extends \Eloquent
{
	protected $table = 'clients';

	public function saleRep()
	{
		return $this->belongsTo('Entities\Staffs\Sale', 'sale_id');
	}
}

Creating API class

<?php namespace Api\Controllers;

use Ratiw\Api\BaseApiController;

class ClientsController extends BaseApiController
{
	protected $model = 'Entities\Clients\Client';
}

Createing Transformer class (optional)

This is optional though. You don't need to create a Transformer if you don't want to transform any field.

<?php namespace Api\Transformers;

use Ratiw\Api\BaseTransformer;

class ClientTransformer extends BaseTransformer
{
	public function transform($client)
	{
		return [
			'id' => (int) $client->id,
			'short_name' => $client->shortname,
			'full_name' => $client->name,
			'sale_id' => $client->sale_id,
			'contact' => $client->contact,
			'email' => $client->email,
			'phone' => $client->phone
		];
	}
}

####Creating Route for the endpoint

Route::group(['prefix' => 'api'], function()
{
    Route::get('clients/{id}', 'Api\Controllers\ClientsController@show');
    Route::get('clients', 'Api\Controllers\ClientsController@index');
    ...
}

Additional Info

####Existing Routes By default, the API package comes ready with two methods

  • index() for querying the collection
  • show() for querying specific item

You should be able to test it via your browser. Just go to http://localhost or http://localhost:8000 or whatever appropriate in your development environment. However, if you've setup your environment different than that, you will have to create a configuration file for that.

Note: If you use Google Chrome browser, you can install JSONView from Chrome Web Store to help prettify the JSON result.

####Allowable Domain Configuration The API class, by default, will first check to see if the calling party is from the allowable host or domain. If it is originate from the domain other than the ones configured, it will return an error.

By default, the allowable hosts are:

  • localhost
  • localhost:8000

In order to change this or add more hosts, you will need to create a configuration file in the app/config directory like so,

// app/config/api.php

<?php

return [
    'allow_hosts' => [
        'localhost:8000',
        'localhost'
        'myawesome.app:8000',  //<-- your addition allowable domain
    ],

    'allow_paths' => [
        'api/*'
    ]	
];

####Sort Operations Sort operation can be done by passing sort parameter in the query string when calling the Api controller.

http://localhost:8000/clients?sort=shortname

To sort in descending order, just prepend the sort column with -

http://localhost:8000/clients?sort=-shortname

####Filtering Results The results can be filtered by specifying the the q parameter in the query string.

http://localhost:8000/clients?q=John

By default, it will perform where clause on the field named code, which will cause error if your model does not have code field. You can fix this by overriding the search() method, like so.

	...
	protected function search($query, $q)
	{
		return $query->where('shortname', 'like', "%$q%")
			->orWhere('name', 'like', '%$q%');
	}
	...

####Specifing Default Filters If you want to always apply specific conditions to the query result, you can do so by overriding getDefaultFilters function. The query builder object will be passed to this function and you can apply any condition you want.

class ClientsController extends BaseApiController
{
	...
    public function getDefaultFilters($query)
    {
        return $query->where('sale_id', Auth::id());
    }
	...
}

####Paginated Results The returned or transformed result is paginated by default to 10 records. To change this, just pass per_page parameter on the query string.

http://localhost:8000/clients?per_page=20

####Limiting Transformed Output Fields You can limit the fields to be returned by supplying the fields parameter on the query string, like so.

http://localhost:8000/clients?fields=id,name

####Eager Load the results To eager load the result of the query, just specifying it in the $eagerLoads array property of the Api class.

...
class ClientsController extends BaseApiController
{
	$protected $eagerLoads = ['saleRep'];
	...
}

####Specifying Transformer class API package will automatically looks for a corresponding Transformer class using the following criteria:

  • Use the Transformer class specified in $transformer property. If the Transformer does not exist, exception will be thrown.
  • Use the base name of the specified $model property to guess the Transformer class. If the Transformer class does not exist, the Ratiw\Api\BaseTransformer class will be used.

This provides enough ease and flexibility. If your project is small and not so complicated, you can just put the Api classes and Transformer classes in the same directory. Or, you won't even have to define any Transformer for the Api class if you do not need to transform anything.

But if your project is quite complex or you prefer putting things in directory where you can organized things neatly, you have the flexibility to do so by specifying the $transformer class to use in the Api class.

...
class ClientsController extends BaseApiController
{
	protected $model = 'Entities\Clients\Client';

	protected $transformer = 'Api\Transformers\ClientTransformer';
	...
}
...

####Overriding Transformer Path By default, the Api class will look for its associated Transformer class in the same directory, but you can override this by putting the transformer_path in the app/config/api.php file.

<?php
return [
	'allowable_path' => [...];
	...
	'transformer_path' => 'Api\\Transfomers\\';
];

Note the double backslash \\ in the path. Double backslash at the end is not required though.

####Embedded Resources in Transformer Embbed resources (nested resources) can be included using the machanism defined by Fractal.

...
class ClientTransformer extends BaseTransformer
{
	protected $defaultIncludes = ['saleRep'];

	public function transform($client)
	{
		...
	}

    public function includeSaleRep($client)
    {
        $saleRep = $client->saleRep;

        return $this->item($saleRep, new SaleTransformer);
    }

}