请求处理管道
增加或减少功能需要重新组织相应过程,即实例化对象的顺序;Laravel框架是通过服务容器进行自动化实例化,
实例间的功能调用也是通过闭包函数完成的,这里我们为了简化,我们将通过静态函数来避免实例化过程,只
仿真通过闭包函数完成装饰者模式,实现请求的处理管道
在理解代码之前,先了解一下array_reduce
array_reduce
array_reduce — 用回调函数迭代地将数组简化为单一的值
说明
array_reduce ( array $array , callable $callback [, mixed $initial = NULL ] ) : mixed
array_reduce()将回调函数callback迭代地作用到array数组中的每一个单元中,从而将数组简化为单一的值。
参数
array
输入的array
callback
callback( mixed $carry , mixed $item ) : mixed
carry
携带上次迭代里的值; 如果本次迭代是第一次,那么这个值是 initial。
item
携带了本次迭代的值。
initial
如果指定了可选参数 initial,该参数将在处理开始前使用,或者当处理结束,数组为空时的最后一个结果。
返回值
返回结果值
initial参数,array_reduce()返回NULL
<?php
interface Middleware
{
public static function handle(Closure $next);
}
class VerifyCsrfToken implements Middleware
{
public static function handle(Closure $next)
{
echo "verify Csr Token ".'<br>';
$next();
}
}
class ShareErrorFromSession implements Middleware
{
public static function handle(Closure $next)
{
echo "share it if the variable of 'error' is existing in SESSION" . '<br>';
$next();
}
}
class StartSession implements Middleware
{
public static function handle(Closure $next)
{
echo "starting a SESSION, Getting data" .'<br>';
$next();
echo "saving data, Closing a Session" .'<br>';
}
}
class AddQueuedCookiesToResponse implements Middleware
{
public static function handle(Closure $next)
{
$next();
echo "adding a cookie for next request" .'<br>';
}
}
class EncryptCookies implements Middleware
{
public static function handle(Closure $next)
{
echo "Decrypting Cookies for input request" .'<br>';
$next();
echo "Encrypt cookie for output response" .'<br>';
}
}
class CheckForMaintenceMode implements Middleware
{
public static function handle(Closure $next)
{
echo "checking the state of program is maintenance mode" .'<br>';
$next();
}
}
function getSlice()
{
return function($stack, $pipe){
return function() use ($stack, $pipe){
return $pipe::handle($stack);
};
};
}
function then()
{
$pipe = [
"CheckForMaintenceMode",
"EncryptCookies",
"AddQueuedCookiesToResponse",
"StartSession",
"ShareErrorFromSession",
"VerifyCsrfToken",
];
$firstSlice = function(){
echo "take request submit to router , and return the response".'<br>';
};
$pipe = array_reverse($pipe);
call_user_func(
array_reduce($pipe, getSlice(), $firstSlice)
);
}
then();
输出
checking the state of programer is maintenance mode
Decrypting Cookies for input request
starting a SESSION, Getting data
share it if the variable of 'error' is existing in SESSION
verify Csr Token
take request submit to router , and return the response
saving data, Closing a Session
adding a cookie for next request
Encrypt cookie for output response
上面实例代码的主要部分就是call_user_func(array_reduce($pipe, getSlice(), $firstSlice)
部分的理解;这部分也是最晦涩、难理解的部分;
根据array_reduce()
接口功能属性(文章前面已经详细给出),画图分析这部分程序执行过程;
首先得理解array_reduce这个接口的使用,从上图可知array_reduce执行完成后,最后返回的是一个包含了6层的闭包对象;
call_user_func执行的时候从最外面那一层开始执行,此时$pipe
的值为CheckForMaintenanceMode
也就是首先调用
CheckForMaintenanceMode类的静态方法handle(),所以我们看到的第一条输出是checking the state of programer is maintenance mode
;
执行$next()
时,其实就是执行CheckForMaintenanceMode::handle()
方法中传入的闭包对象;
从图中可知,CheckForMaintenanceMode::handle($stack)
中的$stack
值是包含5层的闭包对象,而此时$pipe
的值为EncryptCookies
;
即执行EncryptCookies::handle($stack)
返回输出Decrypting Cookies for input request
;
以此类推就可以很容易分析上述出输出结果;