Reputation: 2068
I want to have a different middleware for each individual route like you can do with names. E.g.
Route::resource('posts', 'PostsController', [
'names' => [
'index' => 'custom-index-name',
'store' => 'custom-store-name'
]
]);
But I want to do it with middleware but it doesn't seem like this is possible. Is there a way to do this?
Upvotes: 2
Views: 759
Reputation: 33
In Laravel 9 and from the official documentation:
Or, you may find it convenient to specify middleware within your controller's constructor. Using the middleware method within your controller's constructor, you can assign middleware to the controller's actions:
class UserController extends Controller
{
/**
* Instantiate a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('auth');
$this->middleware('log')->only('index');
$this->middleware('subscribed')->except('store');
}
}
Laravel 9 Controller Documentation
Upvotes: 0
Reputation: 116
Laravel not support middleware for each actions on router resource
My solution: Override Route Illuminate\Routing\Route@middleware
Step 1: Create my Route and overide middleware: app/Services/Helpers/Route.php
namespace App\Services\Helpers;
use Illuminate\Routing\Route as RoutingRoute;
class Route extends RoutingRoute
{
/**
* Get or set the middlewares attached to the route.
*
* @param array|string|null $middleware
* @return $this|array
*/
public function middleware($middleware = null)
{
$this->filterMiddleware();
return parent::middleware($middleware);
}
/**
* Assign permission middleware only for action of route resource
*
* @return void
*/
private function filterMiddleware()
{
$controller = $this->action['controller'] ?? null;
if (!$controller || !is_string($controller)) {
return;
}
$action = explode('@', $this->action['controller'])[1] ?? null;
if (!$action || !is_string($action)) {
return;
}
// Illuminate\Routing\ResourceRegistrar::$resourceDefaults
$acceptActions = ['index', 'create', 'store', 'show', 'edit', 'update', 'destroy'];
foreach ($this->action['middleware'] as $key => $middleware) {
if (is_string($key) && in_array($key, $acceptActions) && $action !== $key) {
unset($this->action['middleware'][$key]);
}
}
}
}
Step 2: Create my Router: app/Services/Router.php
namespace App\Services;
use App\Services\Helpers\Route;
use Illuminate\Routing\Router as RoutingRouter;
class Router extends RoutingRouter
{
/**
* Create a new Route object.
*
* @param array|string $methods
* @param string $uri
* @param mixed $action
* @return \App\Http\Controllers\Admin\Route
*/
public function newRoute($methods, $uri, $action)
{
return (new Route($methods, $uri, $action))
->setRouter($this)
->setContainer($this->container);
}
}
Step 3: add to bootstrap/app.php
to Recreate Router Singleton:
// custom router for this project
$app->singleton('router', App\Services\Router::class);
Step 4: Use on my routes/admin.php
// Role
Route::resource('roles', 'RoleController')
->only(['index', 'show', 'store', 'update', 'destroy'])
->middleware([
'index' => 'permission:roles.show',
'show' => 'permission:roles.show',
'store' => 'permission:roles.create',
'update' => 'permission:roles.update',
'destroy' => 'permission:roles.delete',
]);
Upvotes: 1
Reputation: 459
https://laravel.com/docs/5.7/controllers#controller-middleware
This says that you can restrict middleware to controller methods using $this->middleware(...)->only('...');
This method should allow you to still use Route::resource(...)
.
Upvotes: 3
Reputation: 15175
you can do by route facade by create a seperate route of app each action like this
Route::post('/add','userController@add')->middleware('addMiddleware');
Route::post('/edit','userController@edit')->middleware('editMiddleware');
you can add multiple middleware
Route::post('/delete','userController@delete')->middleware([addMiddleware::class,editMiddleware::class]);
for more info see middleware
Upvotes: 0