Jeff
Jeff

Reputation: 2068

Individual middleware for resource routes?

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

Answers (4)

John Smith
John Smith

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

Tran Dong
Tran Dong

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

Chris Ruskai
Chris Ruskai

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

Jignesh Joisar
Jignesh Joisar

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

Related Questions