中间件在 Laravel 5 中如何工作?

How does middleware work in Laravel 5?

我正在尝试了解中间件在 Laravel 5 中的工作原理。我查看了中间件接口,了解到我必须实现一个 class,它有一个名为 "handle" 的方法。在 "handle" 方法中,调用了闭包。但是我不明白,应该在闭包中传递什么。什么 class 会调用我的中间件?它是如何工作的?可能就像 "foreach" 一样,所有的中间件都会被轮流调用? 更新: 我正在尝试实现自己的中间件:

interface Middleware
{
    public function handle($request, Closure $next);
}

class MiddlewareCollection
{
    private $middlewares;
    private $request;

    public function __construct(Array $middlewares, $request)
    {
        $this->middlewares = $middlewares;
        $this->request = $request;
    }

    public function run()
    {
        $this->next(current($this->middlewares), $this->request);
    }

    private function next(Middleware $middleware, $request)
    {
        $middleware->handle($request, function($request) {
        //How can I call the next middleware?
        });

    }
}

class FirstMiddleware implements Middleware
{
    public function handle($request, Closure $next) {
        echo $request.'first ';
        return $next($request);
    }
}

class SecondMiddleware implements Middleware
{
    public function handle($request, Closure $next) {
        echo $request.'second ';
        return $next($request);
    }
}

class ThirdMiddleware implements Middleware
{
    public function handle($request, Closure $next) {
        echo $request.'third ';
        return $next($request);
    }
}


$middlewares = [
    'first'     => new FirstMiddleware(),
    'second'    => new SecondMiddleware(),
    'third'     => new ThirdMiddleware()
];

$middlewareCollection = new MiddlewareCollection($middlewares, 'Request');

$middlewareCollection->run();

这样做对不对?我也无法理解我应该如何在 MiddlewareCollection class.

的 next() 方法中调用下一个中间件

这个 blog post 对于解释中间件的工作原理以及如何从头开始构建中间件非常有用。

不过,我将使用 Laravel 附带的示例,auth 中间件 (app/Http/Middleware/Authenticate.php)。此中间件保护路由并确保尝试访问它们的用户已登录。

public function handle($request, Closure $next)
    {
        if ($this->auth->guest()) {
            if ($request->ajax()) {
                return response('Unauthorized.', 401);
            } else {
                return redirect()->guest('auth/login');
            }
        }

        return $next($request);
    }

handle 函数为我们完成所有工作,在这种情况下,它首先接受 $request,这是我们想要去的地方或我们发送的请求到服务器。

接下来我们将检查用户是否已登录或者是 if ($this->auth->guest()) 的访客 如果我们登录,那么这将 return false 并且我们将继续 return $next($request); 这将允许我们照常进行。 如果我们没有登录并且是访客,我们将此语句作为 true 传递并继续 if 语句。

然后我们会点击:

if ($request->ajax()) {
                return response('Unauthorized.', 401);
            }

这可能是不言自明的,但它会检查请求是否是 ajax 调用,如果是,那么它将 return 401 未经授权的响应。

如果它不是 ajax 请求,那么我们点击:

else {
                return redirect()->guest('auth/login');
            }

这会将访客重定向到登录页面。一旦他们登录,请求就可以继续,他们的请求将照常进行。

因此,我可以使用此中间件保护路由 www.mywebsite.com/admin,如果我没有登录,那么我将被重定向到 www.mywebsite.com/auth/login,一旦我登录,我将 return 到我原来的要求 www.mywebsite.com/admin 没有任何问题。

正如我首先提到的,请查看该博客 post,因为它确实有一些有用的解释和更简单的示例。

中间件,在Laravel之前的5个被称为filter。中间件拦截请求然后在你的中间件里面处理 class 负责接下来的工作就做什么。根据您的处理方式,有两种类型的中间件。

在控制传递给控制器​​之前检查前中间件。逻辑在您的 handle 方法中。比如,您想在留言簿上登录到 post。所以,如果你在应用中间件之前使用,你的逻辑就像

  • 检查用户是否未登录
  • 将他们重定向回登录页面
  • 否则,让请求按原样进行
代码将是这样的,

public function handle($request, Closure $next)
{
    // Perform action

    return $next($request);
}



after 中间件在控制器完成其所有工作后进行检查,并将响应传递给用户。为此,您可以将其视为已发出 API 请求,并且您希望在每个请求完成时刷新令牌。为此,代码将是

public function handle($request, Closure $next)
{
    $response = $next($request);

    // Perform action

    return $response;
}

在这里,为了简单起见,您可以考虑 $next 方法,因为它会将控制权传递给控制器​​。对于之前的中间件,它会检查逻辑,然后将 return 控件传递给控制器​​,最后 return 响应。
另一方面,after 中间件将控制传递给控制器​​,当控制器完成其工作时,某些内容将存储在 $response 变量中并执行一些逻辑。之后是 returning $response。

希望现在清楚了。