即使路由模型绑定失败,如何在 Laravel 中运行中间件?

问题描述 投票:0回答:1

我在 Laravel 中为我的应用程序构建功能时遇到问题,因为它有奇怪的隐式路由模型绑定逻辑。

我为具有隐式绑定模型的管理面板配置了一些路由。示例如下:

Route::get('/admin/books/{book}', BooksController);

我显然还为所有管理路由提供了一个全局中间件,用于检查用户是否已通过管理员身份验证,如果不是管理员,则将其路由到登录页面。

class AuthenticateAdmin
{
   public function handle(Request $request, Closure $next): Response
   {
      dump('inside admin auth middleware');
      if (! Auth::user()?->is_admin) {
         return to_route('admin.signin');
      }
      return $next($request);
   }
}

我面临的问题是,如果我访问不存在的路线,例如

/admin/books-non-existent
,我会得到正确的重定向,因为中间件确实启动了。也就是说,我收到转储消息

但是,如果我访问存在的路线,但模型绑定失败,例如

/admin/books/xyz
,中间件根本不会运行!我没有收到任何转储消息。

如何让中间件在路由模型绑定失败时也运行?

php laravel route-model-binding
1个回答
0
投票

出现此问题是因为 Laravel 尝试在运行中间件之前绑定模型。如果模型绑定失败(例如,/admin/books/xyz,其中 xyz 不是有效 ID),它会抛出 ModelNotFoundException,跳过中间件。

解决方案:在Handler.php中捕获异常 在 app/Exceptions/Handler.php 中,您可以处理此异常以确保中间件逻辑仍然运行:

use Illuminate\Database\Eloquent\ModelNotFoundException;

public function render($request, Throwable $exception)
{
    if ($exception instanceof ModelNotFoundException) {
        if ($request->is('admin/*')) {
            if (! Auth::user()?->is_admin) {
                return redirect()->route('admin.signin');
            }
            return redirect()->route('admin.books.index'); // or any fallback route
        }
    }

    return parent::render($request, $exception);
}

说明: Laravel 在中间件之前运行模型绑定,因此当绑定失败时,中间件不会被触发。 通过捕获 Handler.php 中的异常,您可以确保中间件逻辑(如管理检查)在模型绑定失败时仍然运行。 这应该可以解决您的问题!

© www.soinside.com 2019 - 2024. All rights reserved.