路由基础知识

在 PHP 应用程序中,象是 XF2,我们需要一种能够接受用户对特定 URL 的请求的方法,了解该 URL 代表的 controller、 action 和数据,以便向用户提供适当的响应。 将一个 URL 転换为代码中的一个位置的概念被称为 "路由"。

在 XF2 中,路由选择几乎完全由 Admin CP 中的一个位置管理。 该位置是 Admin CP > Development > Routes。 路由按两种类型之一分组,即 Public 和 Admin 类型,它们分别在 Public 和 Admin 应用程序中提供请求的路由。

简単的例子

在路由页面 (见上文),你应该看到一个 account/ 的条目。 这是一个 Public 路由,提供了对 URL index.php?account/ 的请求的路由。 这个路由非常简単,它只包含了少量的配置。 值得注意的是,它由一个 "路由前缀",一个 Section context 和一个 Controller class 组成。 让我们更详细地了解这些部分:

路由前缀

路由前缀主要是指在 index.php? 之后和第一个 / 之前的位置。 它是确定路由请求给哪个 Controller 的第一步。

Section context

此 Section context 告诉 XF 中的导览系统,当访问者浏览由该路由転到的页面时,应该选择哪个导览项。 对于 Public 路由,Section context 应该是最高级别导览项的 ID。 对于 Admin 路由,应该是最特定的管理导览条目的 ID(无论深度)。

如果是账户路由,默认情况下,Section context 不一定适用,因为我们没有 "account" 导览标签。 但是,要想看到这个 action,只需将这里的 "Section context" 值改为 "forums",保存更改并在前端进入你的账户。 现在,你应该看到 "Forums" 导览标签被选中了!

Controller

这是当请求与这个路由匹配时,应该被调用的 Controller 的 class 名。 在 "account/" 路由中,我们指定了 XF:Account。 这将加载 Account 控制器。 (更多信息请参见 短类名)。 代码位于以下位置 src/XF/Pub/Controller/Account.php。 注意短类名是如何解析为 "infix" 以及前缀 (XF) 和后缀 (Account) 的。 在本例中,这个控制器的下标 (Pub) 是由 Account 路由类型 (public) 推断出来的。

Controller action

上面我们解释了如何将路由匹配到一个特定的 Controller,但我们还不知道如何调用该 Controller 内的特定 action。 Controller 本质上是一个包含了许多 action 方法的 class,URL 中 路由前缀 后面的部分表示 Controller 的 action。 给定一个 URL 为 index.php?account/account-details,你应该被路由到 XF/Pub/Controller/Account class 和 actionAccountDetails() 方法。 如果路由没有指定 action,那麽调用的方法只是 actionIndex()

你可以在 控制器基础知识 部分阅读更多关于控制器的内容。

更进阶的例子(路由格式)

让我们看看 members/ 路由。 这个路由和 account/ 路由一样,还是很简単的,但是它多了一个字段:"路由格式"。 要了解它是如何工作的,看看你自己在前端的用户个人资料。 该配置文件的 URL 看起来会是这样的 index.php?members/your-name.1。具体而言,请注意 your-name.1 的部分。 这是我们试图使用 "路由格式" 来匹配的部分。

"路由格式" 允许我们从请求 URL 中提取数据,因此我们可以将该信息传递到 Controller action 中,以便该 action 可以加载特定的信息;在这种情况下,它加载请求的用户个人资料的详细信息。 它还可以帮助我们从传递进来的数据中创建链接。 下面是语法:

:int<user_id,username>/:page

有趣的是,此时要注意的是,个人资料 URL 中用于查找个人资料的重要部分其实并不是 your-name 这一点,而实际上是用户ID(1)。 为了证明这一点,改变 URL,用 not-your-name 代替 your-name。 你会看到找到了正确的个人资料,并且重新定向到了正确的 URL。

上面的格式表明它是一个基于整数的参数。 在创建外部链结时,我们从传入数据的 user_id key 中提取整数。 如果数据中传递了一个用户名,它将被 "slugified",就象你在你的个人资料的 URL 中看到的整数 ID 一样。 对于匹配传入的 URL,这将变成一个匹配整数参数格式的范式表达式。

:page 是用于生成链接的 page-123 部分的快捷方式。 在这种情况下,它在链接参数中寻找页面。 如果找到了,它就会被放在 URL 中,然后从参数中删除。 对于传入的解析,如果匹配(它可以是空的),它将把页码添加到传递给 Controller 的参数中。

路由参数

当路由与特定的 Controller 和 action 匹配时,URL 中的任何参数都会被封装到一个特殊的物件中,我们称之为 ParameterBag。 这个物件专门用于将普通 URL 参数与来自路由匹配的 URL 参数分开的。 ParameterBag 物件被传递到每个 Controller action 中,使用方法如下:

$userId = $params->user_id;

Sub-names

也可以将路由分割成更多的 Sub-names。 你可以通过 members/following 路由来看到这个 action。 在这个例子中,following 是路由 members 的 Sub-names。 通常情况下,看起来象 index.php?members/following 的 URL,following 的部分将表示 action,并简単地与普通的 members/ 路由进行匹配。 但是,如果有一个路由匹配了前缀 "members" 和后面的 "Sub-names",就会被使用。 这里也是如此,所以它创建了一个像是下面的链接:

members/:int<user_id,username>/following/:page

对于传入路由的匹配,该路由将在基本成员路由之前进行测试;如果匹配,则使用该路由。

这种 sub-name 系统允许行为改变,例如改变参数的位置或者将路由分组到不同的 Controller 中或使用不同的参数。 您可以在资源管理器和媒体库附加组件中看到后者的例子。