# Symfony\Component\HttpKernel\EventListener\RouterListener public function onKernelRequest(GetResponseEvent $event) { // 路由已经解析过的话就直接返回 if ($request->attributes->has('_controller')) { return; }
# Syfmony\Component\Routing\Router\Router public function matchRequest(Request $request) { $matcher = $this->getMatcher(); if (!$matcher instanceof RequestMatcherInterface) { // fallback to the default UrlMatcherInterface return $matcher->match($request->getPathInfo()); }
return $matcher->matchRequest($request); }
public function getMatcher() { // $this->getConfigCacheFactory() -> Symfony\Component\Config\ResourceCheckerConfigCacheFactory // 获取存储路由信息的文件 var/prod/appProdProjectContainerUrlMatcher.php $cache = $this->getConfigCacheFactory()->cache($this->options['cache_dir'].'/'.$this->options['matcher_cache_class'].'.php', //当路由文件没有生成的时候 这个匿名方法执行,通过配置文件生成路由关系且存储到缓存文件 function (ConfigCacheInterface $cache) { // ...... } );
//这里加载并实例化了缓存的路由信息 var/cache/dev/app[ENV]DebugProjectContainerUrlMatcher.php require_once $cache->getPath(); return $this->matcher = new $this->options['matcher_cache_class']($this->context); }
# Symfony\Component\HttpKernel\Controller\ControllerResolver public function getController(Request $request) { // 这里的变量 $controller 就是从$request 的 attributes属性中获取的,这个属性的数据是 事件 KernelEvents::CONTROLLER中的handler RouterListener 设置的 // 下面的代码逻辑主要是对控制器不同类型的处理 匿名回调 数组 对象 等 if (!$controller = $request->attributes->get('_controller')) { if (null !== $this->logger) { $this->logger->warning('Unable to look for the controller as the "_controller" parameter is missing.'); }
return false; }
if (is_array($controller)) { return $controller; }
if (is_object($controller)) { if (method_exists($controller, '__invoke')) { return $controller; }
throw new \InvalidArgumentException(sprintf('Controller "%s" for URI "%s" is not callable.', get_class($controller), $request->getPathInfo())); }
if (false === strpos($controller, ':')) { if (method_exists($controller, '__invoke')) { return $this->instantiateController($controller); } elseif (function_exists($controller)) { return $controller; } }
$callable = $this->createController($controller);
if (!is_callable($callable)) { throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable. %s', $request->getPathInfo(), $this->getControllerError($callable))); }
if (!$resolved instanceof \Generator) { throw new \InvalidArgumentException(sprintf('%s::resolve() must yield at least one value.', get_class($resolver))); } //$resolver 返回的是 Generator yield foreach ($resolved as $append) { $arguments[] = $append; }
// continue to the next controller argument continue 2; // 跳转到上一层循环继续 }
throw new \RuntimeException(sprintf('Controller "%s" requires that you provide a value for the "$%s" argument. Either the argument is nullable and no null value has been provided, no default value has been provided or because there is a non optional argument after this one.', $representative, $metadata->getName())); }
return $arguments; }
public static function getDefaultArgumentValueResolvers() { return array( new RequestAttributeValueResolver(), new RequestValueResolver(), new SessionValueResolver(), new DefaultValueResolver(), new VariadicValueResolver(), ); }