Laravel 中间件、管道之面向切面编程
Laravel中间件是什么
Laravel 中间件提供了一种方便的机制来过滤进入应用的 HTTP 请求。例如,Laravel 内置了一个中间件来验证用户的身份认证。如果用户没有通过身份认证,中间件会将用户重定向到登录界面。但是,如果用户被认证,中间件将允许该请求进一步进入该应用。
当然,除了身份认证以外,还可以编写另外的中间件来执行各种任务。例如:CORS 中间件可以负责为所有离开应用的响应添加合适的头部信息;日志中间件可以记录所有传入应用的请求。
Laravel 自带了一些中间件,包括身份验证、CSRF 保护等。所有这些中间件都位于 app/Http/Middleware 目录。
简单来说就是请求在不去修改自身的逻辑,通过中间件扩展或者处理一些功能。
和面向切面编程的关系
在我理解Laravel中间件和切面编程就是一个意思,就是都需要经过经过的一些步骤,不去修改自己的代码,以此来扩展或者处理一些功能。举个生活中的例子电影院验票。验票员就是所谓的中间件,每个买票的同学都需要经过他的验证才能进入影院看电影。
如何实现中间件
我们也采用面向接口编程的形式,来定义我们的中间件:
interface Milldeware {
public static function handle(Closure $next);
}
class VerfiyCsrfToekn implements Milldeware {
public static function handle(Closure $next)
{
echo '验证csrf Token <br>';
$next();
}
}
class VerfiyAuth implements Milldeware {
public static function handle(Closure $next)
{
echo '验证是否登录 <br>';
$next();
}
}
class SetCookie implements Milldeware {
public static function handle(Closure $next)
{
$next();
echo '设置cookie信息!';
}
}
$handle = function() {
echo '当前要执行的程序!';
}
function call_middware() {
SetCookie::handle(function (){
VerfiyAuth::handle(function() {
VerfiyCsrfToekn::handle($handle);
});
});
}
call_middware();
下面我们来说一下call_middware都做了什么事
- 第一步执行call_middware 函数 会执行 SetCookie::handle。
- 当执行SetCookie::handle的时候会发现要先执行$next();在echo '设置cookie信息!';
- 所以就先执行了VerfiyAuth::handle,这时候会先执行echo '验证是否登录 <br>';然后执行 $next();
- 执行 VerfiyCsrfToekn::handle 这时候会先执行echo '验证csrf Token <br>';然后执行 $next();
- 执行 $handle();
- 最后 在echo '设置cookie信息!'。
明白了其中原理,有些同学想这样代码肯定不会很好维护和扩展啊。那我们应该怎么去修改我们的代码呢?
首先,希望同学能先知道两个函数的使用
1.call_user_func(); 2.array_reduce();
具体两个函数的作用请先查看php文档。
interface Milldeware {
public static function handle(Closure $next);
}
class VerfiyCsrfToekn implements Milldeware {
public static function handle(Closure $next)
{
echo '验证csrf Token <br>';
$next();
}
}
class VerfiyAuth implements Milldeware {
public static function handle(Closure $next)
{
echo '验证是否登录 <br>';
$next();
}
}
class SetCookie implements Milldeware {
public static function handle(Closure $next)
{
$next();
echo '设置cookie信息!';
}
}
$handle = function() {
echo '当前要执行的程序!';
};
$pipe_arr = [
'VerfiyCsrfToekn',
'VerfiyAuth',
'SetCookie',
];
$callback = array_reduce($pipe_arr,function($stack,$pipe) {
return function() use($stack,$pipe){
return $pipe::handle($stack);
};
},$handle);
call_user_func($callback);
最后的实现就是这样子的。当然laravel中实现middware也是主要通过call_user_func和array_reduce() 实现的
3 Comments
第一段代码需要修正一下
$pipe_arr = [ 'VerfiyCsrfToekn', 'VerfiyAuth', 'SetCookie', ]; 这里的顺序为什么要反过来,顺序这哥没理解。麻烦大佬解释下
array_reduce里面直接return 的闭包,顺序执行到SetCookie那里$next()才开始执行,这时的$next就是上次VerfiyAuth::handle()方法,输出内容后再次执行$next,此时的$next是VerfiyCsrfToekn::handle()方法,然后就执行$handle这个方法,此时SetCookie里的$next方法执行完,最后输出执行 echo '设置cookie信息!'; 这是我的理解,不知道对不对