您的位置:首页 > 编程语言 > PHP开发

laravel/lumen 接口执行时间记录以及前后置中间件terminate的使用

2020-04-24 07:33 841 查看

routemidlleware 不支持 terminate 这是基于什么考虑的。不管 laravel 还是 lumen 只有 global middleware 才会去 call terminate 而 routemiddleware 却不会

中间件文件都放在app/http/Middleware文件夹中,可以根据ExampleMiddleware.php进行创建


 前置中间件

[code]namespace App\Http\Middleware;

use Closure;

define('START', microtime(true));

class BeforeMiddleware
{
//第三个参数为额外传参
public function handle($request, Closure $next)
{
//前置中间件,在执行路由定义指定的操作前做你想做的事情

return $next($request);
}
}

后置中间件

[code]<?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() 调用参数数组中。

[code]$app->middleware([
App\Http\Middleware\Authenticate::class,
]);

Terminable中间件

有些时候中间件需要在 HTTP 响应被发送到浏览器之后才运行,例如,「session」中间件存储的 session 数据是在响应被发送到浏览器之后才进行写入的。想要做到这一点,你需要定义中间件为「terminable」。 

[code]<?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
 方法注册中间件。

 

[code]$app->singleton(
App\Http\Middleware\terminable::class
);

 如果上面的代码个别接口执行不到terminate的话(这里是坑,至今未找到原因),你可以尝试以下方法

在底层控制器中的的构造方法__construct中注册函数register_shutdown_function

注册一个 

callback
 ,它会在脚本执行完成或者 exit() 后被调用。

可以多次调用 register_shutdown_function() ,这些被注册的回调会按照他们注册时的顺序被依次调用。 如果你在注册的方法内部调用 exit(), 那么所有处理会被中止,并且其他注册的中止回调也不会再被调用

[code]public function __construct()
{
register_shutdown_function(array($this, 'test'));
}

public function test()
{
//成功完成后置中间件里的内容
// TODO 切记 请勿die/exit
}

以上是本人总结的方法和遇到的坑,如果有更好的方案,欢迎提出

  • 点赞 1
  • 收藏
  • 分享
  • 文章举报
WXiangQian王先森 博客专家 发布了84 篇原创文章 · 获赞 232 · 访问量 11万+ 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: