laravel/lumen 接口執行時間記錄以及先後置中間件terminate的使用

routemidlleware 不支持 terminate 這是基於什麼考慮的。無論 laravel 仍是 lumen 只有 global middleware 纔會去 call terminate 而 routemiddleware 卻不會php

中間件文件都放在app/http/Middleware文件夾中,能夠根據ExampleMiddleware.php進行建立laravel

前置中間件

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() 調用參數數組中。bootstrap

$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 會從 服務容器 解析一個全新的中間件實例。bash

若是你但願在 handleterminate 方法被調用時使用一致的中間件實例,只需在容器中使用容器的 singleton 方法註冊中間件。session


$app->singleton(
    App\Http\Middleware\terminable::class 
);
複製代碼

若是上面的代碼個別接口執行不到terminate的話(這裏是坑,至今未找到緣由),你能夠嘗試如下方法app

在底層控制器中的的構造方法__construct中註冊函數register_shutdown_function函數

註冊一個 callback ,它會在腳本執行完成或者 exit() 後被調用。ui

能夠屢次調用 register_shutdown_function() ,這些被註冊的回調會按照他們註冊時的順序被依次調用。 若是你在註冊的方法內部調用 exit(), 那麼全部處理會被停止,而且其餘註冊的停止回調也不會再被調用

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

public function test()
{
    //成功完成後置中間件裏的內容
    // TODO 切記 請勿die/exit
}複製代碼

以上是本人總結的方法和遇到的坑,若是有更好的方案,歡迎提出

相關文章
相關標籤/搜索