Skip to content

Instantly share code, notes, and snippets.

@ajcastro
Created August 17, 2019 12:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ajcastro/338ed57e0e46c6497d839139c10151c9 to your computer and use it in GitHub Desktop.
Save ajcastro/338ed57e0e46c6497d839139c10151c9 to your computer and use it in GitHub Desktop.
BaseCrudController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Services\Paginator\Paginator;
use Illuminate\Database\QueryException;
use Illuminate\Validation\ValidationException;
abstract class BaseCrudController extends Controller
{
/**
* Model for this crud operation.
* @var \Illuminate\Database\Eloquent\Model
*/
protected $model;
/**
* Request validation rules.
*
* @var array
*/
protected $rules = [];
/**
* Exclude this params from request when getting params for store and update.
*
* @var array
*/
protected $except = ['_token'];
/**
* Resource response format.
*
* @var mixed
*/
protected $resourceResponse;
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
if (request()->has('all')) {
return $this->paginatorQuery()->get()->map(function ($row) {
if ($this->resourceResponse) {
return transform($row, $this->resourceResponse);
}
return $row;
});
}
return $this->respondIndex($this->newPaginator()->query()->response());
}
/**
* Return the query for the paginator.
*
* @return \Illuminate\Database\Query\Builder
*/
protected function paginatorQuery()
{
return $this->model->query();
}
/**
* Return a new paginator builder.
*
* @return \App\Services\Paginator\Paginator
*/
protected function newPaginator()
{
return new Paginator($this->paginatorQuery(), request(), $this->resourceResponse());
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$this->save($model = $this->model->newInstance($this->inputStore()));
$this->onStore($model);
return $this->respondStore($model);
}
/**
* Update hook for the model.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @return void
*/
protected function onStore($model)
{
return;
}
/**
* Return the response for index route.
* May transform paginator and model.
*
* @param Paginator $paginator
* @return Paginator
*/
protected function respondIndex($paginator)
{
return $paginator;
}
/**
* Return resource response format.
*
* @return mixed
*/
protected function resourceResponse()
{
return $this->resourceResponse;
}
/**
* Return the response for the store route.
* May transform model.
*
* @param Model $model
* @return mixed
*/
protected function respondStore($model)
{
return response($model, 201);
}
/**
* Return the response for the store route.
* May transform model.
*
* @param Model $model
* @return mixed
*/
protected function respondShow($model)
{
if ($resource = $this->resourceResponse()) {
return transform($model, new $resource);
}
return $model;
}
/**
* Return the response for the update route.
* May transform model.
*
* @param Model|null $model
* @return mixed
*/
protected function respondUpdate($model = null)
{
return response('', 200);
}
/**
* Return the request.
* May apply modifications on request.
*
* @return request
*/
protected function request()
{
return request();
}
/**
* Get model attributes input for storing model.
* Request validation happens here.
*
* @return array
*/
protected function inputStore()
{
$request = $this->requestStore();
if ($rules = $this->rulesStore($request)) {
$this->validate($request, $rules);
}
return array_merge($request->except($this->except), $this->inputStoreAppends($request));
}
/**
* Get model attributes input for storing model.
* Request validation happens here.
*
* @param Model $model
* @return array
*/
protected function inputUpdate($model = null)
{
$request = $this->requestUpdate($model);
if ($rules = $this->rulesUpdate($request, $model)) {
$this->validate($request, $rules);
}
return array_merge($request->except($this->except), $this->inputUpdateAppends($request));
}
/**
* Get the request for store.
*
* @return Request
*/
protected function requestStore()
{
return $this->request();
}
/**
* Get the request for update.
*
* @param Model $model
* @return Request
*/
protected function requestUpdate($model = null)
{
return $this->request();
}
/**
* Return validation rules.
*
* @param Request $request
* @return array
*/
protected function rules($request = null)
{
return $this->rules;
}
/**
* Return validation rules for store.
*
* @param Request $request
* @return array
*/
protected function rulesStore($request = null)
{
return $this->rules($request);
}
/**
* Return validation rules for update.
*
* @param Request $request
* @param Model $model
* @return array
*/
protected function rulesUpdate($request = null, $model = null)
{
return array_only($this->rules($request), array_keys($request->except($this->except)));
}
/**
* Append attributes for store request.
*
* @param Request $request
* @return array
*/
protected function inputStoreAppends($request)
{
return [];
}
/**
* Append attributes for update request.
*
* @param Request $request
* @param Model $model
* @return array
*/
protected function inputUpdateAppends($request, $model = null)
{
return [];
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
return $this->respondShow($this->getShow($id));
}
/**
* Get the resource model for show api.
*
* @param int $id
* @return mixed
*/
protected function getShow($id)
{
return $this->get($id);
}
/**
* Get the resource model for update api.
*
* @param int $id
* @return \Illuminate\Database\Eloquent\Model
*/
protected function getUpdate($id)
{
return $this->get($id);
}
/**
* Get the resource model for update api.
*
* @param int $id
* @return \Illuminate\Database\Eloquent\Model
*/
protected function getDestroy($id)
{
return $this->get($id);
}
/**
* Get for the resource model.
*
* @param int $id
* @return \Illuminate\Database\Eloquent\Model
*/
protected function get($id)
{
return $this->model->findOrFail($id);
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
$model = $this->getUpdate($id);
$model->fill($this->inputUpdate($model));
$this->save($model);
$this->onUpdate($model);
return $this->respondUpdate($model);
}
/**
* Update hook for the model.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @return void
*/
protected function onUpdate($model)
{
return;
}
/**
* Save model from create or update.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @return void
*/
protected function save($model)
{
$model->save();
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
$model = $this->getDestroy($id);
try {
$model->delete();
} catch (QueryException $e) {
if ($e->errorInfo[0] == 23000 && $e->errorInfo[1] == 1451) {
throw ValidationException::withMessages([
'id' => [
'Cannot delete data, already in use.'
]
]);
}
throw $e;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment