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 会从 服务容器 解析一个全新的中间件实例。

如果你希望在 handleterminate 方法被调用时使用一致的中间件实例,只需在容器中使用容器的 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
}

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


文章作者: WXiangQian
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 WXiangQian !
 上一篇
git如何修改已经commit的name和email git如何修改已经commit的name和email
自己的github仓库发现每次提交的name和email不统一,尝试去修改已经commitname和email 因为更换过电脑,设置的—global name 和email 邮箱和以前的不一样了,想更换为以前的样子 于是尝试了好多方法,终
2019-08-01
下一篇 
phpstorm2018.3注册码汇总(持续更新) phpstorm2018.3注册码汇总(持续更新)
phpstorm2018.3注册码汇总(持续更新) 以前经常用lanyu的http://idea.lanyus.com/ 最新phpstorm码(更新于2020-01-04)QYYBAC9D3J-eyJsaWNlbnNlSWQiOiJRWV
2019-05-10
  目录