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() 後被調用。

可以多次調用 register_shutdown_function() ,這些被註冊的回調會按照他們註冊時的順序被依次調用。 如果你在註冊的方法內部調用 exit(), 那麼所有處理會被中止,並且其他註冊的中止回調也不會再被調用

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

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

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章