【问题标题】:How does middleware work in Laravel 5?中间件在 Laravel 5 中是如何工作的?
【发布时间】:2016-02-13 03:03:57
【问题描述】:

我试图了解中间件在 Laravel 5 中是如何工作的。我查看了中间件接口并明白我必须实现一个类,该类有一个名为“handle”的方法。在“handle”方法中,调用闭包。但我不明白,关闭时应该通过什么。什么类会调用我的中间件?它是如何在引擎盖下工作的?可能就像“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 类的 next() 方法中调用下一个中间件。

【问题讨论】:

  • 中间件,以前称为过滤器,由 MiddlewareServiceProvider 处理,它们的逻辑在路由访问时执行,在请求接收之后和请求注入到路由器之前的“中间”某处。
  • 我认为@TheMrbikus 了解中间件的工作流程,但他想了解的是闭包 $next 是在哪里编写和调用的。他向你展示了handle方法如何调用+闭包的逻辑,我想没有人理解他的问题。
  • @Dannyhax 是的,你说得对,兄弟! :) 事实上我已经写了我的中间件调度器。如果你感兴趣github.com/SmirnovW/light-middleware-dispatcher

标签: php laravel middleware


【解决方案1】:

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

在将控制权传递给控制器​​之前检查之前的中间件。逻辑在您的句柄方法中。就像,您希望登录后在您的留言簿上发帖。所以,如果你在应用中间件之前使用,你的逻辑就像

  • 检查用户是否未登录
  • 将他们重定向回登录页面
  • 否则,让请求继续进行
代码将是这样的,
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 方法将控制权传递给控制器​​。在中间件之前,它会检查逻辑,然后将控制权返回给控制器,最后返回响应。
另一方面,中间件将控制权传递给控制器​​,当控制器完成其工作时,会在 $response 变量中存储一些内容并执行一些逻辑。之后它返回 $response。

希望现在清楚了。

【讨论】:

  • 非常感谢您提供这些信息!我更新了我的问题,你能看看我的代码并发表你的意见吗?
  • 我不明白你想要做什么或实现什么。
  • 我尝试实现我自己的中间件一种机制,以了解它是如何工作的 =)
  • 你做错了,中间件不是你应该实例化和运行的东西。有一个工匠命令来创建一个中间件。你可以这样做,这将帮助你创建新的中间件。而且,正如我之前所说,无论您要检查什么(逻辑)都将在 handle 方法中。还有一件事,中间件被注入到路由和控制器构造函数中。并且您必须将该中间件添加到 $routedmiddlware 数组中的 app/Http/Kernel.php 中,并带有稍后从所需位置使用的密钥。看看 -> gist.github.com/ssi-anik/1955cae190394b865657
  • 顺便说一句,如果您认为这让您了解了中间件的基本概念,如果您愿意,可以将其标记为已接受的答案。 :)
【解决方案2】:

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

但是,我将使用 Laravel 随附的示例,即身份验证中间件 (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()) 的访客 如果我们已登录,那么这将返回 false,我们将继续前进到 return $next($request);,这将允许我们照常进行。 如果我们没有登录并且是访客,我们会将此声明作为 true 传递,然后继续使用 if 声明。

然后我们会点击:

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

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

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

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

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

因此,我可以用这个中间件保护路由www.mywebsite.com/admin,如果我没有登录,那么我将被重定向到www.mywebsite.com/auth/login,一旦我登录,我将返回我原来的请求www.mywebsite.com/admin没有任何麻烦。

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

【讨论】:

  • 感谢您提供这些示例,非常有帮助!我更新了我的问题,你能看看我的代码并发表你的意见吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-10
  • 1970-01-01
  • 1970-01-01
  • 2017-09-26
  • 2023-04-04
  • 2015-06-30
  • 2016-07-27
相关资源
最近更新 更多