ChainRouter
Symfony CMF 路由组件的核心是 ChainRouter。它被用作 Symfony 默认路由系统的替代品。
ChainRouter 的工作原理是接受一组具有优先级的路由策略,即 RouterInterface 的实现,通常称为“路由器”。
当处理传入的请求时,ChainRouter 会迭代配置的路由器,并按其配置的优先级排序,直到其中一个能够 匹配 请求或 匹配 URL 并提供请求参数。
注意
从历史上看,路由器必须仅对 URL 字符串进行匹配。自 Symfony 2.2 以来,它可以选择实现 RequestMatcherInterface 以对完整的 Request 对象进行匹配,如果它想考虑其他请求信息,例如域名或 accept-encoding。ChainRouter 支持两种类型的路由匹配。
向链中添加路由器
路由器是使用 ChainRouter 的 add 方法添加的。使用此方法添加默认的 Symfony 路由器
1 2 3 4 5 6
use Symfony\Component\Routing\Router;
use Symfony\Cmf\Component\Routing\ChainRouter;
$chainRouter = new ChainRouter();
$chainRouter->add(new Router(...));
$chainRouter->match('/foo/bar');
现在,当 ChainRouter 匹配请求时,它将询问 Symfony Router 以查看请求是否匹配。如果没有匹配项,它将抛出 ResourceNotFoundException。
如果您添加一个新的路由器,例如 DynamicRouter,它将在 Symfony Router 之后被调用(因为 Symfony Router 是先添加的)。要控制顺序,您可以使用 add 方法的第二个参数来设置优先级。优先级较高的路由器会先排序。
1 2 3 4 5 6 7 8
use Symfony\Cmf\Component\Routing\DynamicRouter;
// ...
$chainRouter->add(new Router(...), 1);
$dynamicRouter = new DynamicRouter(...);
// ...
$chainRouter->add($dynamicRouter, 100);
注意
您将在本文后面的内容中学习如何实例化 DynamicRouter。
注册路由器编译器Pass
此组件提供了一个 RegisterRoutersPass。如果您使用 Symfony 依赖注入组件,则可以使用此编译器 pass 注册所有带有特定标签的路由器
1 2 3 4 5 6 7 8
use Symfony\Cmf\Component\Routing\DependencyInjection\Compiler\RegisterRoutersPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
// a ContainerBuilder
$container = ...;
$pass = new RegisterRoutersPass('cmf_routing.router', 'router');
$container->addCompilerPass($pass);
在添加 pass 并配置容器构建器之后,您可以继续按照 Symfony DI 组件编译部分 中所述编译容器。
您可以选择配置链式路由器服务名称。当从容器加载链式路由器时,编译器 pass 将修改此服务定义以注册路由器。如果您未指定任何内容,则服务名称为 cmf_routing.router。
您还可以使用编译器 pass 构造函数的第二个参数配置要使用的标签名称。如果您不这样做,则默认标签为 router。如果您正在使用 Symfony CMF RoutingBundle,则此标签已使用默认名称激活。
路由器
ChainRouter 本身无法做出任何实际的路由决策。它唯一的作用是管理给定的路由器集合,这些路由器负责匹配请求并确定其参数。
您可以通过实现 RouterInterface 轻松创建自己的路由器,但 Symfony CMF 路由组件已经包含一个强大的路由匹配系统,您可以将其扩展以满足您的需求。
Symfony 默认路由器
Symfony 路由机制本身就是 RouterInterface 的实现,这意味着您可以在 ChainRouter 中将其用作路由器。这使您可以使用默认的路由声明系统。在核心文档的 路由组件 文章中阅读有关此路由器的更多信息。