Laravel 路由组和中间件

Posted

技术标签:

【中文标题】Laravel 路由组和中间件【英文标题】:Laravel route group and middlewares 【发布时间】:2022-01-11 14:38:18 【问题描述】:

我正在与可以验证状态(已验证电子邮件)的用户一起开发一个 laravel 项目。

另一方面,用户可以拥有由“订阅”中间件验证的订阅。

所以我有几组路线,包括 2 组,其中唯一的区别是是否存在订阅

第一组:

Route::group(['middleware' => ["auth:sanctum", "verified"]], function () 

第 2 组

Route::group(['middleware' => ["auth:sanctum", "verified", "subscriptions"]], function () 

我的问题是关于 laravel 用于这些组中的路线的顺序。例如,如果用户满足第一组的所有中间件,laravel 会测试第二组的中间件吗? 已验证的用户是否有机会进入第二组订阅路线?

反之,如果用户没有订阅,则不会通过订阅中间件。但我的印象是用户被订阅中间件重定向失败,而 laravel 可以在没有这个中间件的组中找到正确的路由(组 1)

我想要的是它只是测试是否存在订阅,如果找不到它会在 group1 中查找路由。

代码中组的顺序对处理有影响吗?

谢谢。

编辑:

Route::group(['middleware' => ["auth:sanctum", "verified", ]], function () 
            Route::get("/new", function () 
               // redirect to payment
            )->name("new-payment");
    


Route::group(['middleware' => ["auth:sanctum", "verified", "subscriptions"]], function () 
    Route::get("/new", function () 
        return view("bourse-new");
    )->name("new-abo");

它是相同的路由,但根据订阅的存在与否具有不同的行为 当订阅中间件失败时,它会重定向到“家”,但我希望 laravel 使用第一条路线

【问题讨论】:

实际路线是否不同?你能提供例子吗?您也许可以只嵌套您的组/中间件。 @Peppermintology 感谢您的关注。我想,如果用户有订阅,他可以创建一个新项目,如果没有,他会被重定向到付款。 所以你是说即使subscriptions 中间件返回false 组内的路由是可访问的? @ManojKiranAppathurai,组内的路由无法访问,但由于“订阅”失败,它重定向到“家”,我只是希望它使用第一组的路由,一个没有这个中间件的 否 你不能将相同的 URI 添加到不同的路由 【参考方案1】:

感谢@NoobDev。

我通过将订阅测试集成到中间件来接管他的解决方案

    Route::group(['middleware' => ["auth:sanctum", "verified"]], function () 
        Route::get("/new", function () 
            return view("bourse-new");    
        )->middleware("subscriptions")->name("bourse-new");
    );

和订阅中间件:

    public function handle(Request $request, Closure $next)
        if( //logic tests) 
             return $next($request);
         
         return redirect('/checkout'); //redirect to payment
    

这个解决方案几乎是完美的,谢谢大家

【讨论】:

【参考方案2】:

我的问题是关于 laravel 在这些路线中使用的顺序 团体。例如,如果用户满足所有的中间件 第一组,laravel会测试第二组的中间件吗?

如果您点击了第一组中包含的路线,laravel 将不会检查其他路线。

做一个 用户验证有机会进入第二组路线 订阅?

如果他没有订阅,他就不能

代码中组的顺序对处理有影响吗?

是的,如果您使用相同的 uri,最后一个将覆盖前一个

Route::group(['middleware' => ["auth:sanctum", "verified", ]], function () 
            Route::get("/new", function () 
               // redirect to payment
            )->name("new-payment");
    


Route::group(['middleware' => ["auth:sanctum", "verified", "subscriptions"]], function () 
    Route::get("/new", function () 
        return view("bourse-new");
    )->name("new-abo");

试试 php artisan route:list,第二组可能会覆盖第一组

好的,谢谢,但我想要不同的行为,具体取决于存在 是否订阅

在用户模型中:

public function hasSubscribed()

    //do your logic to check if has subscription

您可以使用第一个组并检查 Auth::user() 是否已订阅。像这样:

if (auth()->user()->hasSubscribed())  
    return view()
 
    
//or ...

【讨论】:

你是对的,有了 route: list,只会出现第二条路线。 你的解决方案太棒了,我想知道为什么我没有想到它。 没什么了不起的!顺便说一句,总是很乐意提供帮助【参考方案3】:

app/Http/Kernel.php

protected $middlewarePriority = [
    \Illuminate\Cookie\Middleware\EncryptCookies::class,
    \Illuminate\Session\Middleware\StartSession::class,
    \Illuminate\View\Middleware\ShareErrorsFromSession::class,
    \Illuminate\Contracts\Auth\Middleware\AuthenticatesRequests::class,
    \Illuminate\Routing\Middleware\ThrottleRequests::class,
    \Illuminate\Routing\Middleware\ThrottleRequestsWithRedis::class,
    \Illuminate\Session\Middleware\AuthenticateSession::class,
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
    \Illuminate\Auth\Middleware\Authorize::class,
];

文档: https://laravel.com/docs/8.x/middleware#sorting-middleware

【讨论】:

以上是关于Laravel 路由组和中间件的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Laravel 中间件适用于单个路由而不适用于一组路由

Vue 路由器和 Laravel 中间件

将 Auth 中间件应用于所有 Laravel 路由

Laravel 在资源路由控制器的特定路由上应用中间件

Laravel 中间件/路由组

将路由参数作为参数发送到中间件 Laravel