PHPackages                             sehrgut/laravel5-api - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. sehrgut/laravel5-api

AbandonedArchivedLibrary[API Development](/categories/api)

sehrgut/laravel5-api
====================

A modular controller for exposing your Laravel 5 Eloquent models as a REST API.

v0.7.10(7y ago)146.5k2[6 issues](https://github.com/sehrgutesoftware/laravel5-api/issues)MITPHPPHP &gt;=5.4

Since Aug 25Pushed 7y ago1 watchersCompare

[ Source](https://github.com/sehrgutesoftware/laravel5-api)[ Packagist](https://packagist.org/packages/sehrgut/laravel5-api)[ Docs](http://github.com/sehrgutesoftware/laravel5-api)[ RSS](/packages/sehrgut-laravel5-api/feed)WikiDiscussions master Synced today

READMEChangelogDependencies (3)Versions (32)Used By (0)

laravel5-api
============

[](#laravel5-api)

[![Gitter Chat](https://camo.githubusercontent.com/a8e59330fbc221ab12637e12615f6d058fb80e946132ae2b52ac7c78faed161a/68747470733a2f2f696d672e736869656c64732e696f2f6769747465722f726f6f6d2f7365687267757465736f6674776172652f6c61726176656c352d6170692e7376673f7374796c653d666c61742d737175617265)](https://gitter.im/sehrgutesoftware/laravel5-api) [![Travis Build Status](https://camo.githubusercontent.com/014c2d59f81af3f5bfc66e1129c79ef9684c1d89f9031b62b7fdd6b08e6993cb/68747470733a2f2f696d672e736869656c64732e696f2f7472617669732f7365687267757465736f6674776172652f6c61726176656c352d6170692f6d61737465722e7376673f7374796c653d666c61742d737175617265)](https://travis-ci.org/sehrgutesoftware/laravel5-api) [![StyleCI Status](https://camo.githubusercontent.com/30cb8ea02c453d5b4750f66e2ee16ebe22e1bccf54829f62d1e9c582cd9e557d/68747470733a2f2f7374796c6563692e696f2f7265706f732f36363535353738392f736869656c64)](https://styleci.io/repos/66555789) [![Code Climate](https://camo.githubusercontent.com/b78d1c60aabe7dfcf323541a7e9234abc32a2b1ca07e63054afca555a84f4009/68747470733a2f2f696d672e736869656c64732e696f2f636f6465636c696d6174652f6769746875622f7365687267757465736f6674776172652f6c61726176656c352d6170692e7376673f7374796c653d666c61742d737175617265)](https://codeclimate.com/github/sehrgutesoftware/laravel5-api)

A modular controller for exposing your Laravel 5 Eloquent models as a REST API. All you need to do is create one subclass of the controller per model and set up the routes.

**Disclaimer: This is an early release! Do not use in production without extensive testing! The API is subject to change!**

**Please use Github Issues for bug reports and feature requests.**

Table of Contents
-----------------

[](#table-of-contents)

- [Documentation](#documentation)
- [Getting Started](#getting-started)
- [Components](#components)
    - [Controller](#controller-1)
    - [Validator](#validator)
    - [Transformer](#transformer)
    - [ModelMapping](#modelmapping)
    - [RequestAdapter](#requestadapter)
- [Customization](#customization)
    - [Plugins](#plugins)
    - [Deprecated: Hook Methods](#deprecated-hook-methods)
- [Changelog](#changelog)
- [Compatibility](#compatibility)
- [Testing](#testing)
- [License](#license)

Documentation
-------------

[](#documentation)

[API Reference v0.7.8](https://sehrgutesoftware.github.io/laravel5-api/api/v0.7.8) ([v0.6.5](https://sehrgutesoftware.github.io/laravel5-api/api/v0.6.5), [v0.5.3](https://sehrgutesoftware.github.io/laravel5-api/api/v0.5.3), [v0.4.2](https://sehrgutesoftware.github.io/laravel5-api/api/v0.4.2), [v0.3.0](https://sehrgutesoftware.github.io/laravel5-api/api/v0.3.0))

Getting Started
---------------

[](#getting-started)

### Install Package

[](#install-package)

```
composer require sehrgut/laravel5-api
```

### Create an Endpoint

[](#create-an-endpoint)

#### Controller

[](#controller)

Subclass `SehrGut\Laravel5_Api\Controller` and set the eloquent model your controller should expose. Example:

```
use SehrGut\Laravel5_Api\Controller as ApiController;
use App\Models\Post;

class PostsController extends ApiController
{
    protected $model = Post::class;
}
```

#### Routes

[](#routes)

You now have a controller with the same handlers as a [Laravel Resource Controller](https://laravel.com/docs/5.4/controllers#resource-controllers). Those methods can now be used to handle the following routes:

```
Route::get('/posts', 'PostsController@index');
Route::post('/posts', 'PostsController@store');
Route::get('/posts/{id}', 'PostsController@show');
Route::put('/posts/{id}', 'PostsController@update');
Route::delete('/posts/{id}', 'PostsController@destroy');
```

#### Mapping route parameters to model attributes

[](#mapping-route-parameters-to-model-attributes)

By default, it is assumed that there is an `{id}` parameter in all urls pointing to a single resource (`show`, `update`, `destroy`). This parameter is then used to find the corresponding model by its `id` attribute.

If your model's primary key or your route parameter have a different name than `id`, you need to manually map these in your Controller's `$key_mapping`. Example:

```
protected $key_mapping = [
	// Maps the `{post_id}` url parameter to the model's `primary_key` attribute/db column
	'post_id' => 'primary_key'
];
```

In the same manner, additional url parameters can be mapped to model attributes. This is especially useful when creating endpoints for nested resources like `/api/v1/posts/{post_id}/comments/{comment_id}`.

### Validators &amp; Transformers

[](#validators--transformers)

You might want to create a *Validator* and a *Transformer* and assign them to your Model in your *ModelMapping*. More on how this works under [Components](#components).

### Error Responses

[](#error-responses)

In order to have Exceptions displayed correctly, make sure to handle `SehrGut\Laravel5_Api\Exceptions\Exception` in your `app/Exceptions/Handler.php`:

```
use SehrGut\Laravel5_Api\Exceptions\Exception as SehrGutApiException;

class Handler extends ExceptionHandler
{
    public function render($request, Exception $exception)
    {
        if ($exception instanceof SehrGutApiException) {
            return $exception->errorResponse();
        }

        // Possibly other checks

        return parent::render($request, $exception);
    }
}
```

### Structure

[](#structure)

In a larger Project with several endpoints, it is reasonable to have a common BaseController where the [ModelMapping](#modelmapping) is defined for all endpoints.

#### Example Directory Structure:

[](#example-directory-structure)

```
app/
|---- PublicApi
|		+---- V1
|			  |---- Controllers
|			  |		|---- BaseController.php
|			  |		|---- PostsController.php
|			  |		+---- PostCommentsController.php
|			  |---- Transformers
|			  |		|---- PostTransformer.php
|			  |		+---- CommentTransformer.php
|			  |---- Validators
|			  |		|---- PostValidator.php
|			  |		+---- CommentValidator.php
|			  |---- ModelMapping.php
|			  +---- RequestAdapter.php
+---- …

```

Components
----------

[](#components)

The logic is divided up into smaller components, each with their own responsibility:

- **Controller** – controls the entire request/response flow
- **Validator** – ensures the request payload is valid
- **Transformer** – applies transformations to the output data
- **ModelMapping** – knows which Validator/Transformer to use for each Model
- **RequestAdapter** – obtains the parameters from the request

### Controller

[](#controller-1)

#### Available Handlers

[](#available-handlers)

- `index()` - Fetch all resources
- `store()` - Create a new resource
- `show()` - Fetch a single resource
- `update()` - Update a single resource
- `destroy()` - Delete a single resource

#### Side-loading and counting relations

[](#side-loading-and-counting-relations)

Side-loads and relationship counts can be added to the response by enumerating the names of the relation in the `$relations` or `$counts` properties on the controller. Both work recursively, allowing to side-load/count nested relations using dot-syntax.

**Example:**

```
use SehrGut\Laravel5_Api\Controller as ApiController;
use App\Models\Post;

class PostsController extends ApiController
{
    protected $model = Post::class;

    protected $relations = [
    	'comments',  // Side-load the 'comments' relation within posts
    	'comments.author'  // Side-load the 'author' relation in nested comments
    ];

    protected $counts = [
    	'comments',	 // Add 'comments_count' to posts
    	'comments.responses'  // Add `responses_count` to nested comments
    ];
}
```

### Validator

[](#validator)

In order to create a custom Validator for a model, you can subclass the `Validator` class and set the `$rules` array. After that, the Validator needs to be registered in the `ModelMapping` which is assigned to your Controller. Please refer to the [ModelMapping](#modelmapping) section on how to do this. A Validator could look like this:

```
use SehrGut\Laravel5_Api\Validator;

class PostValidator extends Validator
{
    protected static $rules = [
        'title' => 'required|min:3|max:100',
        'body' => 'max:65536'
    ];
}
```

### Transformer

[](#transformer)

To shape how your models are represented at the api, you can do some transformatios on the model while generating the response. This works the same way as with Validators. Just subclass `Transformer` and assign them to your models via the `ModelMapping`.

In your Transformer subclass, you can define the following attributes to customize the output:

```
use SehrGut\Laravel5_Api\Transformers\Transformer;

class PostTransformer extends Transformer
{
	// Rename Attributes:
	protected $aliases = [
		'original_attribute_name' => 'new_attribute_name',
		'id' => 'post_id'
	];

	// Remove Attributes:
	protected $drop_attributes = [
		'private_email'
	];

	// Remove Relations:
	protected $drop_relations = [
		'comments'
	];
}
```

Further, you can change the values of individual attributes of your models by defining a `formatAttribute` method on the Transformer where `Attribute` is the camel-case name of the attribute you want to transform. The method should accept a single argument (the original value) and return the transformed attribute. Example:

```
use SehrGut\Laravel5_Api\Transformers\Transformer;

class PostTransformer extends Transformer
{
	/**
	 * Correct the date format of the member_since attribute
	 */
	formatMemberSince($value)
	{
		return $value->toDateString();
	}
}
```

### ModelMapping

[](#modelmapping)

The Controller asks the ModelMapping which Validator and Transformer it should use for each Model and their respective relations. If no Transformer/Validator is assigned to a model, the respctive defaults are returned (No validation, no transformation).

In order to apply custom Transformers or Validators to your models, you have to create a custom model mapping and assign it to your Controllers (preferrably via a common BaseController).

```
use SehrGut\Laravel5_Api\ModelMapping as BaseModelMapping;

use App\Models\Post;
use App\PublicApi\V1\Transformers\PostTransformer;
use App\PublicApi\V1\Validators\PostValidator;

class ModelMapping extends BaseModelMapping
{
	protected $transformers = [
		Post::class =>	PostTransformer::class
	];

	protected $validators = [
		Post::class =>	PostValidator::class
	];
}
```

```
use SehrGut\Laravel5_Api\Controller;

class BaseController extends Controller
{
	protected $model_mapping_class = ModelMapping::class;
}
```

### RequestAdapter

[](#requestadapter)

TBD

Customization
-------------

[](#customization)

### Plugins

[](#plugins)

Plugins are a way of "hooking into" and manipulating the behaviour of controller actions. They replace the old "hooks", used in versions ≤0.3

#### Usage

[](#usage)

Plugins can be registered inside the **Controller** by specifying them in the `$plugins` property. The order of execution will be the order in which they are listed here.

**Example:**

```
use SehrGut\Laravel5_Api\Plugins\Paginator;
use SehrGut\Laravel5_Api\Plugins\SearchFilter;

class PostsController extends BaseController
{
	protected $plugins = [
		Paginator::class,
		SearchFilter::class,
	];
}
```

##### Declaring Hooks on the Controller

[](#declaring-hooks-on-the-controller)

Instead of using Plugins, a controller can also implement any of the [Hooks](#plugin-hooks) itself, in order to influence the request/response lifecycle. In this case, it behaves the same as a Plugin:

1. Declare that the controller `implements` the appropriate Hook Interface
2. Declare the method required by the Interface

If a controller subscribes to a Hook this way, the Hook will first be called on the controller, before it gets handed through the Plugins.

#### Configuration

[](#configuration)

Some plugins have configurable options, that can be set through the controller. This can be done from inside the `afterConstruct()` method like so:

```
use SehrGut\Laravel5_Api\Plugins\SearchFilter;

class PostsController extends BaseController
{
	protected $plugins = [SearchFilter::class];

	protected function afterConstruct()
	{
	    $this->configurePlugin(SearchFilter::class, [
	        'searchable' => ['name', 'description'],  // compare to those fields on the model
	        'search_param' => 'query',                // `?query=some+search+query`
	    ]);
	}
}
```

*Please refer to the source code or API reference of the individual plugin to see the available configuration options.*

#### Available Plugins

[](#available-plugins)

Please [use the source](https://github.com/sehrgutesoftware/laravel5-api/tree/master/src/Laravel5_Api/Plugins) for definite answers. Still, here's a (probably outdated) list of plugins:

- **Authorizaton** runs Authorization checks using Laravel's built-in [Authorization](https://laravel.com/docs/5.2/authorization) on all five default controller actions.
- **Paginator** allows pagination of `index` result sets. By default, it uses the `limit` and `page` query parameters to determine the requested subset.
- **RelationSplitter** is a pretty successful divorce lawyer from Southern… kidding aside, it makes related objects appear under a separate key in the response, instead of nested inside their relatives.
- **SearchFilter** adds text search to `index` queries. You can configure which model attributes to compare the search term with.

**For help on using the individual plugins, check their respective [source files](https://github.com/sehrgutesoftware/laravel5-api/tree/master/src/Laravel5_Api/Plugins) or the [API reference](#documentation)!**

#### Writing Plugins

[](#writing-plugins)

A plugin is just a class that extends `SehrGut\Laravel5_Api\Plugins\Plugin`. It can implement one or more *Hooks* in order to influence the controller's behaviour.

##### Plugin Configuration

[](#plugin-configuration)

The base `Plugin` class provides a `protected $config` attribute, to store configuation options, which are settable through the controller's `configurePlugin($name, $options)` method. Use this feature to expose parameters of your plugin to the user (the person writing the controller). Retrieve config options inside the plugin with `$this->config['option_name']`. Default values should be set via the `protected $default_config` property.

##### Example:

[](#example)

```
