Skip to content

Commit

Permalink
Minor updates
Browse files Browse the repository at this point in the history
Added strict validation to API controller trait
Added support for fractal in models
  • Loading branch information
ezra-obiwale committed Sep 25, 2017
1 parent d0eaaba commit 7fb5800
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 40 deletions.
57 changes: 55 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,55 @@
# larapi
A collection of classes to be extended/used in laravel api applications for quick development
# laraquick

A collection of classes to be extended/used in laravel api applications for quick
development.

## Introduction

The library contains traits with well documented methods that should be used by
controllers and models to enhance coding speed.

## Installation

```
composer require d-scribe/laraquick
```

## Dependencies

- PHP >= 5.6.0
- Laravel - 5.4.*
- Laravel Fractal - ^4.0

## Example

An example controller for a `Book` model is:

```php
use App\Book;
use Laraquick\Controllers\Traits\Api;

class BookController extends Controller {

use Api;

protected function model() {
return Book::class;
}

protected function validationRules($forUpdate = false) {
return [
'title' => 'required|max:200',
'author' => 'required|max:50',
'genre' => 'required'
];
}
}

```

And with just the above, the controller would take care of listing (w/ pagination),
and all `CRUD` operations and give the right JSON responses.

## API Documentation

Coming soon
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
],
"require": {
"php": ">=5.6.0",
"laravel/framework": "5.4.*"
"laravel/framework": "5.4.*",
"spatie/laravel-fractal": "^4.0"
},
"autoload": {
"psr-4": {
Expand Down
111 changes: 77 additions & 34 deletions src/Controllers/Traits/Api.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ trait Api
* @return mixed
*/
abstract protected function model();

/**
* Should return the validation rules
*
Expand All @@ -37,6 +37,38 @@ abstract protected function model();
*/
abstract protected function validationRules($forUpdate = false);

/**
* Indicates whether validation should be strict and throw errors if unwanted
* values exists
*
* @return boolean
*/
protected function strictValidation()
{
return false;
}

/**
* Checks the request data against validation rules
*
* @param array $data
* @param array $rules
* @param boolean $ignoreStrict Indicates whether to ignore strict validation
* @return void
*/
protected function checkRequestData(array $data, array $rules, $ignoreStrict = false)
{
$this->validator = Validator::make($data, $rules);
if ($this->validator->fails())
return $this->error($this->validationErrorMessage(), $this->validator->errors());

if (!$ignoreStrict && $this->strictValidation()) {
$left_overs = collection($data)->except(array_keys($rules));
if ($left_overs->count())
return $this->error('Too many parameters', null, 406);
}
}

/**
* The model to use in the index method. Defaults to @see model()
*
Expand All @@ -47,6 +79,16 @@ protected function indexModel()
return $this->model();
}

/**
* Sets the default pagination length
*
* @return integer
*/
protected function defaultPaginationLength()
{
return 15;
}

/**
* The model to use in the store method. Defaults to @see model()
*
Expand Down Expand Up @@ -167,39 +209,38 @@ protected function beforeDeleteResponse(&$data)
{
}

/**
* Validates request with validation rules
*
* @param array $data
* @param array $rules
* @return void
*/
protected function isValid(array $data, array $rules)
{
$this->validator = Validator::make($data, $rules);
return !$this->validator->fails();
}

/**
* Display a listing of the resource.
* @return Response
*/
public function index()
{
$model = $this->indexModel();
$length = request()->query('length') ? : 50;
$items = is_object($model)
$length = request()->query('length') ? : $this->defaultPaginationLength();
if ($length == 'all')
$data = is_object($model)
? $model->all()
: $model::all();
else
$data = is_object($model)
? $model->simplePaginate($length)
: $model::simplePaginate($length);
if ($resp = $this->beforeIndexResponse($items)) return $resp;
$resp = [];
$items = $items->toArray();
$resp['data'] = $items['data'];
if (count($resp['data'])) {
if ($resp = $this->beforeIndexResponse($data)) return $resp;
$items = $data->toArray();
if (method_exists($model, 'fractality')) {
$data = is_object($model)
? $model->fractality($data)->toArray()
: $model::fractality($data)->toArray();
}
else {
$data = $items['data'];
}
$meta = null;
if (count($data)) {
unset($items['data']);
$resp['meta']['pagination'] = $items;
$meta['pagination'] = $items;
}
return $this->success($resp);
return $this->success($data, 200, $meta);
}

/**
Expand All @@ -209,11 +250,11 @@ public function index()
*/
public function store(Request $request)
{
if (!$this->isValid($request->all(), $this->validationRules()))
return $this->error($this->validationErrorMessage(), $this->validator->errors());
$data = $request->all();
if ($resp = $this->checkRequestData($data, $this->validationRules()))
return $resp;

$model = $this->storeModel();
$data = $request->all();

if ($resp = $this->beforeCreate($data)) return $resp;

Expand All @@ -224,7 +265,8 @@ public function store(Request $request)
if (!$data) return $this->error($this->createFailedMessage(), null, 500);

if ($resp = $this->beforeCreateResponse($data)) return $resp;
return $this->success($data);

return $this->success(method_exists($data, 'fractalize') ? $data->fractalize()->toArray() : $data);
}

/**
Expand All @@ -242,7 +284,7 @@ public function show($id)
if (!$item) return $this->notFound();

if ($resp = $this->beforeShowResponse($item)) return $resp;
return $this->success($item);
return $this->success(method_exists($item, 'fractalize') ? $item->fractalize()->toArray() : $item);
}

/**
Expand All @@ -253,24 +295,25 @@ public function show($id)
*/
public function update(Request $request, $id)
{
if (!$this->isValid($request->all(), $this->validationRules(true)))
return $this->error($this->validationErrorMessage(), $this->validator->errors());
$data = $request->all();
if ($resp = $this->checkRequestData($data, $this->validationRules(true)))
return $resp;

$model = $this->updateModel();

$item = is_object($model)
? $model->find($id)
: $model::find($id);
if (!$item) return $this->notFound();

$data = $request->all();
if ($resp = $this->beforeUpdate($data)) return $resp;

$result = $item->update($data);

if (!$result) return $this->error($this->updateFailedMessage(), null, 500);

if ($resp = $this->beforeUpdateResponse($item)) return $resp;
return $this->success($item);
return $this->success(method_exists($item, 'fractalize') ? $item->fractalize()->toArray() : $item);
}

/**
Expand All @@ -293,6 +336,6 @@ public function destroy($id)
if (!$result) return $this->error($this->deleteFailedMessage(), null, 500);

if ($resp = $this->beforeDeleteResponse($item)) return $resp;
return $this->success($item);
return $this->success(method_exists($item, 'fractalize') ? $item->fractalize()->toArray() : $item);
}
}
8 changes: 5 additions & 3 deletions src/Controllers/Traits/Respond.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ trait Respond {
* @param integer $code
* @return Response
*/
protected function success($data, $code = 200)
protected function success($data, $code = 200, $meta = null)
{
return response()->json([
$resp = [
"status" => true,
"data" => $data
], $code);
];
if ($meta) $resp['meta'] = $meta;
return response()->json($resp, $code);
}

/**
Expand Down
32 changes: 32 additions & 0 deletions src/Models/Traits/Fractal.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php
namespace Laraquick\Models\Traits;

use Iterator;

trait Fractal
{
/**
* Transform the model with fractal
*
* @return void
*/
final public function fractalize()
{
return fractal($this, function () {
return $this->transform();
});
}

/**
* Fractalize many models of this class
*
* @param Iterator $items
* @return void
*/
public static function fractality(Iterator $items)
{
return collect($items)->map([self, 'fractalize']);
}

abstract public function transform();
}

0 comments on commit 7fb5800

Please sign in to comment.