需要

最近因为业务性能的需要,须要依据数据库记录的申请门路(如admin/auth/menu/46/edit)、申请办法(如GET)去匹配路由实例,拿到路由实例后续做一些其余事件。

剖析

其实就是路由的外围性能(将一类申请映射匹配到一个回调类型的变量)。框架自身自带的性能,查找源码是以下代码块实现的:

// Illuminate/Routing/RouteCollection.phppublic function match(Request $request){    // 1. 获取路由汇合    $routes = $this->get($request->getMethod());        // 2. 匹配路由    $route = $this->matchAgainstRoutes($routes, $request);    return $this->handleMatchedRoute($request, $route);}// Illuminate/Routing/AbstractRouteCollection.phpprotected function matchAgainstRoutes(array $routes, $request, $includingMethod = true){    [$fallbacks, $routes] = collect($routes)->partition(function ($route) {        return $route->isFallback;    });    return $routes->merge($fallbacks)->first(function (Route $route) use ($request, $includingMethod) {        // 3. 遍历匹配        return $route->matches($request, $includingMethod);    });}// Illuminate/Routing/Route.phppublic function matches(Request $request, $includingMethod = true){    $this->compileRoute();    foreach ($this->getValidators() as $validator) {        // 4. 遍历验证器验证匹配        if (! $includingMethod && $validator instanceof MethodValidator) {            continue;        }        if (! $validator->matches($this, $request)) {            return false;        }    }    return true;}

代码大略逻辑是:遍历路由汇合,将以后申请丢给四个验证器 UriValidatorMethodValidatorSchemeValidatorHostValidator 去逐个验证匹配,验证器次要去验证匹配申请对象的 pathInfomethodschemehost 信息。

所以只须要批改以后的申请对象的这些信息,丢给下面的 matches 办法就能够实现我须要的性能了。

实现

因为是同一个我的项目,所以 schemehost 与以后申请统一无需批改。而 pathInfomethod 是两个公有属性以及没有找到对应写权限的办法。所以实现一个有能力写属私性的宏办法即可。最终代码如下:

<?phpnamespace App\Support\Macros;use Illuminate\Routing\Route;use Illuminate\Routing\Router;use Illuminate\Support\Arr;use InvalidArgumentException;class RequestMacro{    /**     * 批改属性     */    public function propertyAware(): callable    {        return function ($property, $value){            /** @var \Illuminate\Http\Request $this */            if (! property_exists($this, $property)) {                throw new InvalidArgumentException('The property not exists.');            }            $this->{$property} = $value;            return $this;        };    }         /**     * 匹配路由     */    public function matchRoute(): callable    {        return function ($includingMethod = true){             // 1. 获取路由汇合            /* @var \Illuminate\Routing\RouteCollection $routeCollection */            $routeCollection = app(Router::class)->getRoutes();            /** @var \Illuminate\Http\Request $this */            $routes = is_null($this->method())                ? $routeCollection->getRoutes()                : Arr::get($routeCollection->getRoutesByMethod(), $this->method(), []);            [$fallbacks, $routes] = collect($routes)->partition(function ($route){                return $route->isFallback;            });            return $routes->merge($fallbacks)->first(function (Route $route) use ($includingMethod){                // 2. 遍历匹配                return $route->matches($this, $includingMethod);            });        };    }}

注册申请宏

// App\Providers\AppServiceProviderpublic function register(){    Request::mixin($this->app->make(RequestMacro::class));}

应用示例

$route = request()    ->propertyAware('pathInfo', \Illuminate\Support\Str::start('admin/auth/menu/46/edit', '/'))    ->propertyAware('method', 'GET')    ->matchRoute();dump($route);

原文链接

  • https://www.guanguans.cn