marcot89 / laravel-magic-routes
Magic Routes for Laravel Applications
Requires
Requires (Dev)
- phpunit/phpunit: ^8.0
- sempro/phpunit-pretty-print: ^1.0
README
Create RESTfull routes for your laravel app based on your controller names and namespaces to avoid overrides and define a pattern to your projects routes. It is compatible with laravel 7+.
Installation
Via Composer
$ composer require marcot89/laravel-magic-routes
Usage
Add MagicRoutes
trait to the controller to generate routes for it automatically:
namespace App\Http\Controllers; use MarcoT89\LaravelMagicRoutes\Traits\MagicRoutes; class UserController extends Controller { use MagicRoutes; }
For now there is no route for your controller because you don't have any public
method declared on it. A new route will be generated for every public method added to the controller. So if we add the common crud public methods like this:
namespace App\Http\Controllers; class UserController extends Controller { use MagicRoutes; public function index(...) {...} public function store(...) {...} public function update(...) {...} public function create(...) {...} public function show(...) {...} public function edit(...) {...} public function destroy(...) {...} public function forceDestroy(...) {...} }
We will have these generated routes based on those public methods:
| GET|HEAD | users | users.index | App\Http\Controllers\UserController@index |
| POST | users | users.store | App\Http\Controllers\UserController@store |
| GET|HEAD | users/create | users.create | App\Http\Controllers\UserController@create |
| PUT | users/{user} | users.update | App\Http\Controllers\UserController@update |
| GET|HEAD | users/{user} | users.show | App\Http\Controllers\UserController@show |
| DELETE | users/{user} | users.destroy | App\Http\Controllers\UserController@destroy |
| GET|HEAD | users/{user}/edit | users.edit | App\Http\Controllers\UserController@edit |
| DELETE | users/{user}/force-destroy | users.force-destroy | App\Http\Controllers\UserController@forceDestroy |
# Customize Http Methods for Routes
Any other public method in the controller will be generated a route with a GET http method as default, but you can customize it with a prefix. Let's see an example.
class PostController extends Controller { use MagicRoutes; // Generated route: // GET /posts/{post}/publish public function publish(Post $post) {...} // Generated route: // POST /posts/{post}/publish public function postPublish(Post $post) {...} // Generated route: // PUT /posts/{post}/publish public function putPublish(Post $post) {...} // Generated route: // DELETE /posts/{post}/publish public function deletePublish(Post $post) {...} }
# Route Params
By convention the first parameter will be set before the action name. All other parameters will be added after.
class PostController extends Controller { public function publish(Post $post, $one, $two, $three) {...} }
Will generate:
GET /posts/{post}/publish/{one}/{two}/{three}
# Middlewares
There are two ways to declare a middleware for a controller:
Using Protected Property
class UserController extends Controller { use MagicRoutes; // use a string for one middlware protected $middleware = 'auth'; // or use an array for many middlewares protected $middleware = [ 'auth', 'verified' => ['except' => ['index', 'edit', 'update']], ]; }
Using Constructor
class UserController extends Controller { use MagicRoutes; public function __construct() { $this->middleware('auth'); } }
# Namespaced Routes
The controller namespace will generate a prefix for that route:
namespace App\Http\Controllers\Api\V1; ... class UserController extends Controller { use MagicRoutes; public function index(...) {...} }
Any public method declared in this controller will generate urls with prefix like:
/api/v1/users
And named routes like:
api.v1.users
# Invokable Controllers
If you like to create a controller for every action you can use the invokable controllers in a namespaced that makes sense for your route. Example:
namespace App\Http\Controllers\Posts; class PublishController extends Controller { use MagicRoutes; protected $middleware = 'auth'; protected $method = 'post'; // only works for invokable controllers // or protected $method = 'post|put'; // separate by pipe for more http methods public function __invoke(Post $post) {...} }
This will generate an URL like:
POST /posts/publish/{post} -> name: posts.publish
# Nested RESTfull Routes
Sometimes you want or need to define nested resources. Let's say we have posts of a user but we want nested routes for that. You can do it with a namespaced controller like this:
namespace App\Http\Controllers\Users; // Note that it is inside Users namespace for prefix route class PostController extends Controller { use MagicRoutes; protected $prefix = '{user}'; public function index(User $user) { return $user->posts()->paginate(); } }
This will generate the following route:
GET /users/{user}/posts -> name: users.posts.index
# Resource URLs Plural vs Singular
RESTfull resources is always in plural. So the convention defines URL resources in plural no matter the name of the controller. If your controller is UserController
or UsersController
both will generate the same resource URL /users
.
But you can disable this behavior using the plural
property:
class UserController extends Controller { use MagicRoutes; protected $plural = false; ... }
With this property false
will generate routes following the controller name. Now if your controller is UserController
it will generate a route /user
. If it is UsersController
it will generate /users
.
Note: For invokable controllers the plural property is always disabled.
Change log
Please see the changelog for more information on what has changed recently.
Contributing
Please see contributing.md for details and a todolist.
Security
If you discover any security related issues, please email author email instead of using the issue tracker.
Credits
MIT License
Please see the license file for more information.