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

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() 后被调用。

扫描二维码关注公众号,回复: 8487163 查看本文章

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

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

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

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

发布了76 篇原创文章 · 获赞 112 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/qq175023117/article/details/91823684