<commit_before># laravel5-api

A modular controller for exposing your Laravel 5 Eloquent models as a REST API. All you need to do is to 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.**

## Documentation
[API Reference](https://sehrgutesoftware.github.io/laravel5-api/api/)

## Getting Started
```bash
composer require sehrgut/laravel5-api
```

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

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

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

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

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

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

### 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:

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


## 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
- **Formatter** – defines the response format and structure

### Controller
#### 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

### 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:

```php
use SehrGut\Laravel5_Api\Validator;

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

### 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:

```php
use SehrGut\Laravel5_Api\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:

```php
use SehrGut\Laravel5_Api\Transformer;

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

### 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).

```php
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
	]
}
```

```php
use SehrGut\Laravel5_Api\Controller;

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

### RequestAdapter
TBD
<commit_msg>Update readme: fix code examples<commit_after># laravel5-api

A modular controller for exposing your Laravel 5 Eloquent models as a REST API. All you need to do is to 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.**

## Documentation
[API Reference](https://sehrgutesoftware.github.io/laravel5-api/api/)

## Getting Started
```bash
composer require sehrgut/laravel5-api
```

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

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

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

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

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

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

### 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:

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


## 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
- **Formatter** – defines the response format and structure

### Controller
#### 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

### 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:

```php
use SehrGut\Laravel5_Api\Validator;

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

### 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:

```php
use SehrGut\Laravel5_Api\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:

```php
use SehrGut\Laravel5_Api\Transformer;

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

### 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).

```php
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
	];
}
```

```php
use SehrGut\Laravel5_Api\Controller;

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

### RequestAdapter
TBD

{'fraction_non_alphanumeric': 0.10820863247123952, 'fraction_numerical': 0.004324885390537151, 'mean_word_length': 4.355257063455303, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 17, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4239367', 'n_tokens_mistral': 3409, 'n_tokens_neox': 3180, 'n_words': 1238}