一,路由服务类
举例:Route::post('/form', 'Form@index'); 发生了什么
#Route详单于IlluminateSupportFacadesRoute,最后返回的是IlluminateRoutingRouter实例 #代理路由注册类RouteRegistrar的方法 __call($method, $parameters) { if (static::hasMacro($method)) { return $this->macroCall($method, $parameters); } return (new RouteRegistrar($this))->attribute($method, $parameters[0]); } #IlluminateRoutingRouteRegistrar的魔术方法 __call($method, $parameters) { if (in_array($method, $this->passthru)) { return $this->registerRoute($method, ...$parameters); } if (in_array($method, $this->allowedAttributes)) { return $this->attribute($method, $parameters[0]); } } #RouteRegistrar的attributes()方法,返回$this $this->attributes[array_get($this->aliases, $key, $key)] = $value; #RouteRegistrar的registerRoute()方法,返回$this $this->router->{$method}($uri, $this->compileAction($action)) #RouteRegistrar的compileAction()方法,返回attributes和action if (is_null($action)) { return $this->attributes; } if (is_string($action) || $action instanceof Closure) { $action = ['uses' => $action]; } return array_merge($this->attributes, $action); #Router的addRoute($methods, $uri, $action)方法 $this->routes->add($this->createRoute($methods, $uri, $action)); #RouteCollection的add(Route $route)方法,返回Route实例支持链式操作 $this->routes[$method][$domainAndUri] = $route; $this->allRoutes[$method.$domainAndUri] = $route; $this->nameList[$action['as']] = $route; $this->actionList[trim($action['controller'], '\')] = $route;
二,注册路由
路由文件api.php,web.php如何被加载
#AppProvidersRouteServiceProvider服务类继承自 IlluminateFoundationSupportProvidersRouteServiceProvider #核心代码 public function map() { $this->mapApiRoutes(); $this->mapWebRoutes(); } protected function mapWebRoutes() { Route::middleware('web') ->namespace($this->namespace) ->group(base_path('routes/web.php')); } protected function mapApiRoutes() { Route::prefix('api') ->middleware('api') ->namespace($this->namespace) ->group(base_path('routes/api.php')); } #router的 group(array $attributes, $routes) { $this->updateGroupStack($attributes);//修改$groupStack属性,因为Router是单例 $this->loadRoutes($routes); array_pop($this->groupStack);//必须还原$groupStack属性 } #router的 loadRoutes($routes) { if ($routes instanceof Closure) { $routes($this); } else { $router = $this; require $routes;//加载路由文件的位置 } }
三,查找匹配路由
如何从Request中找到匹配的路由
#Router的findRoute($request)方法 findRoute($request) { $this->current = $route = $this->routes->match($request); $this->container->instance(Route::class, $route); return $route; } #RouteCollection的match(Request $request)方法 public function match(Request $request) { $routes = $this->get($request->getMethod()); $route = $this->matchAgainstRoutes($routes, $request); if (! is_null($route)) { return $route->bind($request); } $others = $this->checkForAlternateVerbs($request); if (count($others) > 0) { return $this->getRouteForMethods($request, $others); } throw new NotFoundHttpException; } #RouteCollection的matchAgainstRoutes(Request $request)方法 matchAgainstRoutes(array $routes, $request, $includingMethod = true) { return Arr::first($routes, function ($value) use ($request, $includingMethod) { return $value->matches($request, $includingMethod); }); } #Route的 matches(); compileRoute(); $this->compiled = (new RouteCompiler($this))->compile(); IlluminateRoutingRouteCompiler ->compile() SymfonyComponentRoutingRoute ->compile() SymfonyComponentRoutingRouteCompiler ::compile() SymfonyComponentRoutingCompiledRoute对象 //最终的$this->compiled; getValidators(); return static::$validators = [ new UriValidator, #匹配path和where new MethodValidator, #匹配method(GET,POST...) new SchemeValidator, #匹配schema(http或者https) new HostValidator, #匹配host(hostname+port) ];