├── LICENSE.md ├── composer.json ├── readme.md └── src └── ResourceController.php /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Matt Daneshvar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "matt-daneshvar/rest", 3 | "description": "General implementation for Laravel 5 resource controllers", 4 | "keywords": ["laravel", "restful controller", "resource controller"], 5 | "type": "library", 6 | "license": "MIT", 7 | "authors": [ 8 | { 9 | "name": "Matt Daneshvar", 10 | "email": "matt.daneshvar@gmail.com" 11 | } 12 | ], 13 | "require-dev": { 14 | "phpunit/phpunit": "^8.2", 15 | "orchestra/testbench": "^3.8", 16 | "illuminate/http": "5.*", 17 | "illuminate/database": "5.*" 18 | }, 19 | "autoload": { 20 | "psr-4": { 21 | "MattDaneshvar\\ResourceController\\": "src/" 22 | } 23 | }, 24 | "autoload-dev": { 25 | "psr-4": { 26 | "MattDaneshvar\\ResourceController\\Tests\\": "tests/" 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Resource Controller for Laravel 2 | ![Packagist Version](https://img.shields.io/packagist/v/matt-daneshvar/rest.svg) 3 | [![Build Status](https://travis-ci.org/matt-daneshvar/laravel-resource-controller.svg?branch=master)](https://travis-ci.org/matt-daneshvar/laravel-resource-controller) 4 | ![GitHub](https://img.shields.io/github/license/matt-daneshvar/laravel-resource-controller.svg) 5 | 6 | 7 | General implementation for Laravel resource controllers. 8 | 9 | By assuming a few conventions this package takes care of the repetitive implementation of 10 | the CRUD (create, read, update, and delete) operations on a base controller which you can 11 | fully customize and extend to your liking. 12 | 13 | ## Installation 14 | Require the package using composer: 15 | ``` 16 | composer require matt-daneshvar/rest 17 | ``` 18 | ## Usage 19 | Extend the `ResourceController` and specify a `$resource`. Optionally define a `$rules` 20 | property to enforce validation before `store` and `update` operations. 21 | 22 | ```php 23 | 'required|max:200']; 33 | } 34 | ``` 35 | The `TasksController` in the example above will now have general implementation for all CRUD actions. 36 | That includes: 37 | * A `create` method that returns the `tasks.create` view. 38 | * A `show` method that returns the `tasks.show` view injected with the relevant `Task` model. 39 | * A `create` method that returns the `tasks.create` view. 40 | * A `store` method that validates* the request against `$rules`, persists a `Task` object, 41 | and redirects user back to the url corresponding to the `TasksController@index` action. 42 | * An `edit` method that returns the `tasks.edit` view injected with the relevant `Task` model. 43 | * An `update` method that validates* the request against `$rules`, updates the relevant `Task` object, 44 | and redirects user back to the url corresponding to the `TasksController@index` action. 45 | * A `destory` method that deletes the relevant `Task` object, and redirects user back to the url corresponding to the `TasksController@index` action. 46 | 47 | *should the validation fail, user is redirected `back()` with all inputs and errors flashed to the session. 48 | 49 | ## Routing 50 | This package is designed to match Laravel's resource controllers. 51 | Creating a route rule for this controller is simple: 52 | ```php 53 | Route::resource('tasks', 'TasksController'); 54 | ``` 55 | 56 | ### Limiting the exposed CRUD operations 57 | While extending `ResourceController` automatically includes all CRUD operations in your controller, you may wish 58 | to limit the available operations available for your specific resource. You could achieve that 59 | by limiting the routes you expose in your application: 60 | ```php 61 | Route::resource('tasks', 'TasksController', ['only' => ['index', 'show']]); 62 | ``` 63 | 64 | ## Validation 65 | Most real-world applications would validate `store` and `update` requests before 66 | persisting anything to the database. 67 | 68 | Specifying a `$rules` property on your controller, informs the `ResourceController` to validate user's 69 | request against those rules in both `store` and `update` operations. 70 | 71 | ```php 72 | class TasksController extends ResourceController 73 | { 74 | protected $resource = Task::class; 75 | 76 | protected $rules = ['name' => 'required|max:200']; 77 | } 78 | ``` 79 | 80 | If you wish to use different rules for `store` and `update` operations, you may specify them separately: 81 | 82 | ```php 83 | class TasksController extends ResourceController 84 | { 85 | protected $resource = Task::class; 86 | 87 | protected $storeRules = ['name' => 'required|max:200']; 88 | 89 | protected $updateRules = ['name' => 'required|max:200']; 90 | } 91 | ``` 92 | 93 | ## Pagination 94 | In most situations, your application's `index` would use pagination instead of dumping your models into 95 | the view all at once. The `ResourceController` assumes `20` items per page. To change this number define the 96 | `$perPage` attribute, or set it to `null` to disable pagination altogether. 97 | ```php 98 | class TasksController extends ResourceController 99 | { 100 | protected $resource = Task::class; 101 | 102 | protected $perPage = 10; 103 | } 104 | ``` 105 | 106 | ## Other configurations 107 | While assuming a set of default conventions with sensible defaults to minimize code repetition 108 | in most cases, this package is also packed with a bunch of configuration options to allow you 109 | override the default behaviour when needed. 110 | 111 | ```php 112 | class TasksController extends ResourceController 113 | { 114 | /** 115 | * The resource class name. 116 | * 117 | * @var string 118 | */ 119 | protected $resource = ''; 120 | 121 | /** 122 | * The number of models to return for pagination. 123 | * 124 | * @var int|null 125 | */ 126 | protected $perPage = 20; 127 | 128 | /** 129 | * Path to all views for this controller (dot-separated path from views directory). 130 | * 131 | * @var string 132 | */ 133 | protected $viewsPath = null; 134 | 135 | /** 136 | * Views for different resource actions. 137 | * 138 | * @var array 139 | */ 140 | protected $views = []; 141 | 142 | /** 143 | * Validation rules. 144 | * 145 | * @var array 146 | */ 147 | protected $rules = []; 148 | 149 | /** 150 | * Validation rules for store action. 151 | * 152 | * @var array 153 | */ 154 | protected $storeRules = null; 155 | 156 | /** 157 | * Validation rules for update action. 158 | * 159 | * @var array 160 | */ 161 | protected $updateRules = null; 162 | } 163 | ``` 164 | 165 | ## License 166 | The MIT License (MIT). Please see [License File](LICENSE.md) for more information. 167 | -------------------------------------------------------------------------------- /src/ResourceController.php: -------------------------------------------------------------------------------- 1 | views[$action]) ? $this->views[$action] : $this->viewsPath.'.'.$action); 88 | } 89 | 90 | /** 91 | * ResourceController constructor. 92 | */ 93 | public function __construct() 94 | { 95 | //Set model. 96 | $this->model = new $this->resource(); 97 | 98 | //Set resource name. 99 | $this->resourceName = $this->resourceName ?? strtolower(class_basename($this->resource)); 100 | 101 | //Set views default path. 102 | if ($this->viewsPath === null) { 103 | $this->viewsPath = str_plural($this->resourceName); 104 | } 105 | } 106 | 107 | /** 108 | * Display a listing of the resource. 109 | * 110 | * @return \Illuminate\Contracts\View\View 111 | */ 112 | public function index() 113 | { 114 | if ($this->perPage) { 115 | $items = $this->model->paginate($this->perPage); 116 | } else { 117 | $items = $this->model->all(); 118 | } 119 | 120 | return $this->getViewByAction('index')->with([str_plural($this->resourceName) => $items]); 121 | } 122 | 123 | /** 124 | * Show the form for creating a new resource. 125 | * 126 | * @return \Illuminate\Contracts\View\View 127 | */ 128 | public function create() 129 | { 130 | return $this->getViewByAction('create'); 131 | } 132 | 133 | /** 134 | * Store a newly created resource in storage. 135 | * 136 | * @param \Illuminate\Http\Request $request 137 | * @return \Illuminate\Http\Response 138 | * @throws \Illuminate\Validation\ValidationException 139 | */ 140 | public function store(Request $request) 141 | { 142 | $rules = isset($this->storeRules) ? $this->storeRules : $this->rules; 143 | 144 | $this->validate($request, $rules); 145 | 146 | $this->model->create($request->all()); 147 | 148 | return back(); 149 | } 150 | 151 | /** 152 | * Display the specified resource. 153 | * 154 | * @param int|string $key 155 | * @return \Illuminate\Contracts\View\View 156 | */ 157 | public function show($key) 158 | { 159 | $item = $this->findOrFail($key); 160 | 161 | return $this->getViewByAction('show')->with([$this->resourceName => $item]); 162 | } 163 | 164 | /** 165 | * Show the form for editing the specified resource. 166 | * 167 | * @param int|string $key 168 | * @return \Illuminate\Contracts\View\View 169 | */ 170 | public function edit($key) 171 | { 172 | $item = $this->findOrFail($key); 173 | 174 | return $this->getViewByAction('edit')->with([$this->resourceName => $item]); 175 | } 176 | 177 | /** 178 | * Update the specified resource in storage. 179 | * 180 | * @param \Illuminate\Http\Request $request 181 | * @param int|string $key 182 | * @return \Illuminate\Http\Response 183 | * @throws \Illuminate\Validation\ValidationException 184 | */ 185 | public function update($key, Request $request) 186 | { 187 | $rules = isset($this->updateRules) ? $this->updateRules : $this->rules; 188 | 189 | $this->validate($request, $rules); 190 | 191 | $item = $this->findOrFail($key); 192 | 193 | $item->update($request->all()); 194 | 195 | return back(); 196 | } 197 | 198 | /** 199 | * Remove the specified resource from storage. 200 | * 201 | * @param int|string $key 202 | * @return \Illuminate\Http\Response 203 | */ 204 | public function destroy($key) 205 | { 206 | $item = $this->findOrFail($key); 207 | 208 | $item->delete(); 209 | 210 | return back(); 211 | } 212 | 213 | /** 214 | * Find model based on the specified route key name. 215 | * 216 | * @param string $key 217 | * @return \Illuminate\Database\Eloquent\Model 218 | */ 219 | protected function findOrFail($key) 220 | { 221 | return $this->model->where($this->model->getRouteKeyName(), $key)->firstOrFail(); 222 | } 223 | } 224 | --------------------------------------------------------------------------------