├── LICENSE.md ├── README.md ├── composer.json └── src ├── Create.php ├── Destroy.php ├── Edit.php ├── Index.php ├── ResourceActionBase.php ├── ResourceActions.php ├── Show.php ├── Store.php └── Update.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. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Laravel Resource Actions 2 | 3 | ![Packagist PHP Version Support](https://img.shields.io/packagist/php-v/matt-daneshvar/laravel-resource-actions) 4 | [![Build Status](https://travis-ci.org/matt-daneshvar/laravel-resource-actions.svg?branch=master)](https://travis-ci.org/matt-daneshvar/laravel-resource-actions) 5 | ![GitHub](https://img.shields.io/github/license/matt-daneshvar/laravel-resource-actions.svg) 6 | 7 | 8 | If you've built a dozen Laravel apps and if you're anything like me, 9 | you're tired of rewriting basic CRUD controllers a thousand times. 10 | This package DRYs up your code by extracting those repetitive actions into a few magical traits. 11 | 12 | 13 | ## Installation 14 | 15 | Require the package using composer: 16 | ``` 17 | composer require matt-daneshvar/laravel-resource-actions 18 | ``` 19 | 20 | ## Usage 21 | 22 | Once installed, you can write: 23 | 24 | ```php 25 | class TaskController extends BaseController 26 | { 27 | use Index, Create, Store, Show, Edit, Update, Destroy; 28 | 29 | protected $rules = ['name' => 'required|string|max:250']; 30 | } 31 | ``` 32 | 33 | Instead of: 34 | 35 | ```php 36 | class TaskController extends BaseController 37 | { 38 | protected $rules = ['name' => 'required|string|max:250']; 39 | 40 | public function index() 41 | { 42 | return view('task.index', ['tasks' => Task::paginate(20)]); 43 | } 44 | 45 | public function create() 46 | { 47 | return view('task.create'); 48 | } 49 | 50 | public function store(Request $request) 51 | { 52 | $input = $request->validate($this->rules); 53 | 54 | Task::create($input); 55 | 56 | return back()->with('success', 'A new task is successfully created.'); 57 | } 58 | 59 | public function show(Task $task) 60 | { 61 | return view('task.show', ['task' => $task]); 62 | } 63 | 64 | public function edit(Task $task) 65 | { 66 | return view('task.edit', ['task' => $task]); 67 | } 68 | 69 | public function update(Task $task, Request $request) 70 | { 71 | $input = $request->validate($this->rules); 72 | 73 | $task->update($input); 74 | 75 | return back()->with('success', 'The task is successfully updated.'); 76 | } 77 | 78 | public function destroy(Task $task) 79 | { 80 | $task->delete(); 81 | 82 | return back()->with('success', 'The task is successfully deleted.'); 83 | } 84 | } 85 | ``` 86 | 87 | ### Actions 88 | 89 | #### Index 90 | 91 | The `index` action returns the `resource.index` view with a paginated collection of the relevant model, 92 | so that you may write: 93 | 94 | ```php 95 | class TaskController extends BaseController 96 | { 97 | use Index; 98 | } 99 | ``` 100 | 101 | Instead of: 102 | 103 | ```php 104 | class TaskController extends BaseController 105 | { 106 | public function index() 107 | { 108 | return view('task.index', ['tasks' => Task::paginate(20)]); 109 | } 110 | } 111 | ``` 112 | 113 | #### Create 114 | 115 | The `create` action returns the `resource.create` view, 116 | so that you may write: 117 | 118 | ```php 119 | class TaskController extends BaseController 120 | { 121 | use Create; 122 | } 123 | ``` 124 | 125 | Instead of: 126 | 127 | ```php 128 | class TaskController extends BaseController 129 | { 130 | public function create() 131 | { 132 | return view('task.create'); 133 | } 134 | } 135 | ``` 136 | 137 | #### Store 138 | 139 | The `store` action validates the request against the `$rules`, 140 | persists a new model, 141 | and redirects back with a success message. 142 | For this action you may write: 143 | 144 | ```php 145 | class TaskController extends BaseController 146 | { 147 | use Store; 148 | 149 | protected $rules = ['name' => 'required|string|max:250']; 150 | } 151 | ``` 152 | 153 | Instead of: 154 | 155 | ```php 156 | class TaskController extends BaseController 157 | { 158 | protected $rules = ['name' => 'required|string|max:250']; 159 | 160 | public function store(Request $request) 161 | { 162 | $input = $request->validate($this->rules); 163 | 164 | Task::create($input); 165 | 166 | return back()->with('success', 'A new task is successfully created.'); 167 | } 168 | } 169 | ``` 170 | 171 | #### Show 172 | 173 | The `show` action returns the `resource.show` view with the relevant model, 174 | so that you may write: 175 | 176 | ```php 177 | class TaskController extends BaseController 178 | { 179 | use Show; 180 | } 181 | ``` 182 | 183 | Instead of: 184 | 185 | ```php 186 | class TaskController extends BaseController 187 | { 188 | public function show(Task $task) 189 | { 190 | return view('task.show', ['task' => $task]); 191 | } 192 | } 193 | ``` 194 | 195 | #### Edit 196 | 197 | The `edit` action returns the `resource.edit` view with the relevant model, 198 | so that you may write: 199 | 200 | ```php 201 | class TaskController extends BaseController 202 | { 203 | use Edit; 204 | } 205 | ``` 206 | 207 | Instead of: 208 | 209 | ```php 210 | class TaskController extends BaseController 211 | { 212 | public function edit(Task $task) 213 | { 214 | return view('task.edit', ['task' => $task]); 215 | } 216 | } 217 | ``` 218 | 219 | #### Update 220 | 221 | The `update` action validates the request against the `$rules`, 222 | updates the relevant model, 223 | and redirects back with a success message. 224 | For this action you may write: 225 | 226 | ```php 227 | class TaskController extends BaseController 228 | { 229 | use Update; 230 | 231 | protected $rules = ['name' => 'required|string|max:250']; 232 | } 233 | ``` 234 | 235 | Instead of: 236 | 237 | ```php 238 | class TaskController extends BaseController 239 | { 240 | protected $rules = ['name' => 'required|string|max:250']; 241 | 242 | public function update(Task $task, Request $request) 243 | { 244 | $input = $request->validate($this->rules); 245 | 246 | $task->update($input); 247 | 248 | return back()->with('success', 'The task is successfully updated.'); 249 | } 250 | } 251 | ``` 252 | 253 | #### Destroy 254 | 255 | The `destroy` action deletes the relevant model and redirects back with a success message. 256 | For this action you may write: 257 | 258 | ```php 259 | class TaskController extends BaseController 260 | { 261 | use Destroy; 262 | } 263 | ``` 264 | 265 | Instead of: 266 | 267 | ```php 268 | class TaskController extends BaseController 269 | { 270 | public function destroy(Task $task) 271 | { 272 | $task->delete(); 273 | 274 | return back()->with('success', 'The task is successfully deleted.'); 275 | } 276 | } 277 | ``` 278 | 279 | ### Using All Actions 280 | 281 | If you intend to include all 7 resource actions in your controller, 282 | you may use the `ResourceActions` trait as an alias: 283 | 284 | ```php 285 | class TaskController extends BaseController 286 | { 287 | use ResourceActions; 288 | } 289 | ``` 290 | 291 | Which is equivalent to: 292 | 293 | ```php 294 | class TaskController extends BaseController 295 | { 296 | use Index, Create, Store, Show, Edit, Update, Destroy; 297 | } 298 | ``` 299 | 300 | 301 | ## License 302 | 303 | The MIT License (MIT). Please see [License File](LICENSE.md) for more information. -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "matt-daneshvar/laravel-resource-actions", 3 | "description": "General implementation for Laravel resource actions", 4 | "keywords": ["laravel", "restful actions", "resource actions", "resource controller"], 5 | "type": "library", 6 | "license": "MIT", 7 | "authors": [ 8 | { 9 | "name": "Matt Daneshvar", 10 | "email": "matt.daneshvar@gmail.com" 11 | } 12 | ], 13 | "autoload": { 14 | "psr-4": { 15 | "MattDaneshvar\\ResourceActions\\": "src/" 16 | } 17 | }, 18 | "autoload-dev": { 19 | "psr-4": { 20 | "MattDaneshvar\\ResourceActions\\Tests\\": "tests/" 21 | } 22 | }, 23 | "require": { 24 | "php": "^7.3" 25 | }, 26 | "require-dev": { 27 | "phpunit/phpunit": "^8.5", 28 | "orchestra/testbench": "^5.3" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Create.php: -------------------------------------------------------------------------------- 1 | getViewDirectory(); 12 | 13 | return view("$viewDirectory.create"); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Destroy.php: -------------------------------------------------------------------------------- 1 | getResource()->resolveRouteBinding($key); 12 | 13 | $model->delete(); 14 | 15 | $resourceName = $this->getResourceName(); 16 | 17 | return back()->with('success', "$resourceName is successfully deleted."); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Edit.php: -------------------------------------------------------------------------------- 1 | getResource()->resolveRouteBinding($key); 14 | 15 | $viewDirectory = $this->getViewDirectory(); 16 | 17 | $resourceName = Str::lower($this->getResourceName()); 18 | 19 | return view("$viewDirectory.edit", [$resourceName => $model]); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Index.php: -------------------------------------------------------------------------------- 1 | getViewDirectory(); 14 | 15 | $pluralResourceName = Str::lower(Str::plural($this->getResourceName())); 16 | 17 | return view("$viewDirectory.index", [$pluralResourceName => $this->getResource()->paginate(20)]); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/ResourceActionBase.php: -------------------------------------------------------------------------------- 1 | getResourceName()); 12 | } 13 | 14 | protected function getResource() 15 | { 16 | $class = $this->getResourceClass(); 17 | 18 | return new $class; 19 | } 20 | 21 | protected function getResourceName() 22 | { 23 | return class_basename($this->getResourceClass()); 24 | } 25 | 26 | protected function getResourceClass() 27 | { 28 | if (isset($this->resource)) { 29 | return $this->resource; 30 | } 31 | 32 | $classBasename = str_replace('Controller', '', class_basename($this)); 33 | 34 | $classNameWithModelFolder = "App\Models\\$classBasename"; 35 | 36 | return class_exists($classNameWithModelFolder) ? $classNameWithModelFolder : "App\\$classBasename"; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/ResourceActions.php: -------------------------------------------------------------------------------- 1 | getResource()->resolveRouteBinding($key); 14 | 15 | $viewDirectory = $this->getViewDirectory(); 16 | 17 | $resourceName = Str::lower($this->getResourceName()); 18 | 19 | return view("$viewDirectory.show", [$resourceName => $model]); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Store.php: -------------------------------------------------------------------------------- 1 | validate($this->rules ?? []); 15 | 16 | $this->getResource()->create($input); 17 | 18 | $resourceName = Str::lower($this->getResourceName()); 19 | 20 | return back()->with('success', "A new $resourceName is successfully created."); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Update.php: -------------------------------------------------------------------------------- 1 | getResource()->resolveRouteBinding($key); 15 | 16 | $input = $request->validate($this->rules ?? []); 17 | 18 | $model->update($input); 19 | 20 | $resourceName = Str::lower($this->getResourceName()); 21 | 22 | return back()->with('success', "A new $resourceName is successfully updated."); 23 | } 24 | } 25 | --------------------------------------------------------------------------------