国产+高潮+在线,国产 av 仑乱内谢,www国产亚洲精品久久,51国产偷自视频区视频,成人午夜精品网站在线观看

分享一個實現(xiàn)控制器中間件方法的方式

小Z先生
  • 首先是實現(xiàn)一個中間件ControllerMiddleware
<?php

namespace common\middleware;

use ReflectionClass;
use Throwable;
use Webman\Http\Request;
use Webman\Http\Response;
use Webman\MiddlewareInterface;

/**
 * 控制器中間件
 * Class ControllerMiddleware
 * @package common\middleware
 */
class ControllerMiddleware implements MiddlewareInterface
{
    public function process(Request $request, callable $handler): Response
    {
        $controller = new ReflectionClass($request->controller);
        $exists = method_exists($request->controller, "middlewares");
        //驗證控制器或者其父類是否有middlewares方法
        if (!$exists) {
            return $handler($request);
        }
        $refMethod = $controller->getMethod('middlewares');
        $middlewares = $refMethod->invokeArgs(null, []); //執(zhí)行靜態(tài)方法獲取到控制器中間件配置
        if ($middlewares) {
            $actionMiddlewares = $middlewares[$request->action] ?? []; //標(biāo)識只有這個方法需要執(zhí)行(只有方法執(zhí)行)
            $controllerMiddlewares = $middlewares[""] ?? []; //標(biāo)識整個控制器都需要執(zhí)行(控制器全局)
            $allMiddlewares = array_merge($actionMiddlewares, $controllerMiddlewares);
            if ($allMiddlewares) {
                $callList = [];
                foreach ($allMiddlewares as $m) {
                    if (!is_a($m,MiddlewareInterface::class,true)){
                        continue;
                    }
                    //因為有的是直接配置 Test2Middleware::class
                    //有的則可能是  new Test2Middleware('xxx') 傳參的
                    if (is_string($m)) {
                        $callList[] = [new $m, 'process'];
                    } else {
                        $callList[] = [$m, 'process'];
                    }
                }
                $callback = array_reduce($callList, function ($carry, $pipe) {
                    return function ($request) use ($carry, $pipe) {
                        try {
                            return $pipe($request, $carry);
                        } catch (Throwable $e) {
                            throw $e;
                        }
                    };
                }, function ($request) use ($handler) {
                    return $handler($request);
                });
                return $callback($request, $handler);
            }
        }
        return $handler($request);
    }
}
  • 然后配置到config/middleware.php中 可以配置到超全局@或者全局,模塊的都行
'@' => [
        ControllerMiddleware::class,
],
  • 新增一個測試用的中間件
<?php

namespace common\middleware;

use Webman\Http\Request;
use Webman\Http\Response;
use Webman\MiddlewareInterface;

/**
 * 測試中間件
 * Class CheckDuplicateMiddleware
 * @package common\middleware
 */
class TestMiddleware implements MiddlewareInterface
{
    public function __construct(protected $key = "")
    {
    }

    public function process(Request $request, callable $handler): Response
    {
        var_dump("111 start" . $this->key);
        $res = $handler($request);
        var_dump("111 end" . $this->key);
        return $res;
    }

}
  • 然后在你的控制器中寫一個 middlewares() 方法
/**
* 定義控制器中間件 
* @return array
*/
public static function middlewares()
    {
        //先執(zhí)行方法中間件

        return [
            //控制器都要執(zhí)行的中間件
//            "" => [
//                TestMiddleware::class
//            ],
            //只有請求的方法需要執(zhí)行
//            "add" => [
//                TestMiddleware::class
//                new TestMiddleware("xxxx")
//            ]
        ];
}
612 1 0
1個評論

864328615

我有一個疑問這塊設(shè)計的是否可以基于屬性配置 而不是一個方法,這要會不會更好些,其實就是參考thinkphp的 哈哈

  • 小Z先生 2024-11-02

    一開始其實也是基于屬性配置的
    但是實際操作發(fā)現(xiàn)配置無法配置 new Object("xxx") 這種模式 所以才想改成靜態(tài)方法來配置的
    因為我的實際業(yè)務(wù)是需要配置某個接口的限流或者接口鎖,這時候就需要傳遞一些參數(shù)
    但是使用屬性配置的話無法配置new xx() 這種模式

小Z先生

1290
積分
0
獲贊數(shù)
0
粉絲數(shù)
2023-05-05 加入
??