routemidlleware 不支持 terminate 这是基于什么考虑的。
不管 laravel 还是 lumen 只有 global middleware 才会去 call terminate 而 routemiddleware 却不会。
中间件文件都放在app/http/Middleware文件夹中,可以根据ExampleMiddleware.php进行创建
前置中间件
namespace App\Http\Middleware;
use Closure;
define('START', microtime(true));
class BeforeMiddleware
{
//第三个参数为额外传参
public function handle($request, Closure $next)
{
//前置中间件,在执行路由定义指定的操作前做你想做的事情
return $next($request);
}
}
后置中间件
<?php
namespace App\Http\Middleware;
use Closure;
class AfterMiddleware
{
//第三个参数为额外传参
public function handle($request, Closure $next)
{
$response = $next($request);
//后置中间件,在执行完路由定义指定的操作后(也就是响应前)做你想做的事情
echo 1;
return $response;
}
}
全局中间件
每个 HTTP 请求都经过一个中间件,只要将中间件的类加入到 bootstrap/app.php 的 $app->middleware() 调用参数数组中。
$app->middleware([
App\Http\Middleware\Authenticate::class,
]);
Terminable中间件
有些时候中间件需要在 HTTP 响应被发送到浏览器之后才运行,例如,「session」中间件存储的 session 数据是在响应被发送到浏览器之后才进行写入的。想要做到这一点,你需要定义中间件为「terminable」。
<?php
namespace Illuminate\Session\Middleware;
use Closure;
use Illuminate\Support\Facades\Log;
class StartSession
{
public function handle($request, Closure $next)
{
// 开始
Log::info($_SERVER['REQUEST_URI'].'开始'.START.'微秒');
return $next($request);
}
public function terminate($request, $response)
{
//结束
$end = microtime(true);
Log::info($_SERVER['REQUEST_URI'].'结束'.$end.'微秒');
$diff = ($end-START) * 1000;
if ($diff >= 1500) {
Log::info("接口{".$_SERVER['REQUEST_URI']."}从请求开始到结束相差{$diff}毫秒");
}
}
}
terminate
方法必须接收请求及响应。一旦定义了 terminable 中间件,你便需要将它增加到 bootstrap/app.php
文件的全局中间件清单列表中。
当在你的中间件调用 terminate
方法时,Lumen 会从 服务容器 解析一个全新的中间件实例。
如果你希望在 handle
及 terminate
方法被调用时使用一致的中间件实例,只需在容器中使用容器的 singleton
方法注册中间件。
$app->singleton(
App\Http\Middleware\terminable::class
);
如果上面的代码个别接口执行不到terminate的话(这里是坑,至今未找到原因),你可以尝试以下方法
在底层控制器中的的构造方法__construct中注册函数register_shutdown_function
注册一个 callback
,它会在脚本执行完成或者 exit() 后被调用。
可以多次调用 register_shutdown_function() ,这些被注册的回调会按照他们注册时的顺序被依次调用。 如果你在注册的方法内部调用 exit(), 那么所有处理会被中止,并且其他注册的中止回调也不会再被调用
public function __construct()
{
register_shutdown_function(array($this, 'test'));
}
public function test()
{
//成功完成后置中间件里的内容
// TODO 切记 请勿die/exit
}