使用 Symfony 组件创建自己的 PHP 框架(第四部分:路由组件)

使用 Symfony 组件创建自己的 PHP 框架(第四部分:路由组件)

Chris Yue 5 comments
Posts

英文原文地址:https://symfony.com/doc/current/create_framework/routing.html

在开始我们今天的话题前,我们先重构一下我们的框架,让我们的模板文件更加易读:

由于我们将请求里面的 GET 参数解压(extract)出来了,我们就可以简化模板代码:

现在我们的代码将可以以更好的状态来添加新的功能了。

任何一个网站都有一个重要的要素,那就是他们的 URL 的形式。多亏了有 $map 变量这个映射表,我们将 URL 以及跟他关联的响应这两部分代码从我们的代码里面解耦出来了,但目前还是不够灵活。举个例子,如果你想动态生成 URL,并将 URL 中的一个部分来代替 GET 参数:

想添加这个功能?请先添加 sf 路由组件

用来代替之前$map这个映射关系数组的,是路由组件,它依赖于 RouteCollection 实例来描述映射关系:

让我添加两条路由规则,一条是 /hello/SOMETHING,另一条是简单的 /bye

每一条路由规则都由一个名字(hello)以及一个 Route 实例来定义,而一条路由实例又由一条路由规则(/hello/{name})以及默认值数组(array('name' => 'World'))来定义。

请阅读官方文档学会路由组件其他更多功能,比如 URL 生成器,属性限制,HTTP 方法限制,YAML,XML 配置载入器,规则转储为 PHP 文件甚至 Apache 的 URL 重写规则来获取性能上的提升,以及其他更多功能。

基于 RouteCollection 实例里存储的信息,UrlMatch 对象可实现对 URL 的匹配:

match 方法接受请求路径为参数,然后返回相关的路由属性数组(注意路由的名字已经自动赋值给 _route 属性了):

我们并不严格要求要使用 $context 参数,但在真正的项目中最好还是加上,因为如果你的路由规则除了匹配 URL 还需要匹配 HTTP 的某个方法(译者注:比如 GET、POST 方法),是必须要这个参数的

如果匹配器找不到任何一个匹配规则,他会抛出一个意外:

利用上面的知识点,我们将框架代码重写一下:

此段代码改进以下一些事情:

  • 使用 route 名字作为模板的文件名
  • 500 错误也可以进行控制和管理了
  • 解压后的请求变量让我们的模板文件代码简单许多

  • 路由管理被单独分配到一个文件里面

    现在我们的框架(front.php 里的代码)和配置文件(所有都在 app.php 文件里配置)有了很明确的分工。

我们用不到 30 行的代码便写好了我们新的框架,比之前那个更灵活更强大了。

使用路由组件还有一个很大的好处:利用路由规则生成 URL。如果你使用路由组件来匹配你的 URL,又使用路由组件来生成你的URL(译者注:也就是传说中的『双向路由』),那么你想更换某个路由的规则,可毫无顾忌对系统的影响。想知道如何利用这个功能生成链接?小菜一碟:

代码非常明了,根本不用再重新说明过程了;然后,多亏了有 context 你甚至可以生成全路径:

译者注:任何前段控制器框架,或者说单点入口框架,都会面对路由器性能问题,这个问题甚至被 PHP 之父作为“反对使用框架”的论点之一。事实上,如果一个项目有几十个甚至上百个路由规则,路由器性能的确是一个头痛的问题。sf 的路由转存组件将路由转存为 Apache 的 URL 改写规则,将本来 PHP 就不擅长的路由工作交给特别擅长此工作的 web 服务器,的确是个很靠谱的创新。对性能要求较高的同学可以考虑尝试一下。另外我想既然 Apache 的改写能做,Nginx 的改写规则也应该不远了 2017-01-18 补充:在 Symfony3 里已经不推荐将路由规则转储为 Apache,官方的描述是『为了一点点的性能提升,而需要每次在路由规则有变化的时候去更新 Apache 的改写规则是不划算的』。可能 Symfony3 在路由性能这方面已经优化得足够好了,再加上 PHP7 的性能提升,已经没有必要这么做了

返回阅读第三部分 | 继续阅读第五部分

使用 Symfony 组件创建自己的 PHP 框架(第四部分:路由组件) by Chris Yue is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.

微信赞赏码

文章不错,我要帮站长分担建站费!
天使投赏人

5 Comments

duqingnian

十月 2, 2012 在 5:18 下午

请教博主,为什么在替换autoload这步骤的时候require_once __DIR__.’/../vendor/.composer/autoload.php’; 我没有.composer 我只有composer 没有前面的小数点 而且里面没有autoload.php这个文件啊 , 何解?

    Chris Yue

    十月 12, 2012 在 2:04 下午

    开发环境以及composer版本说一下呢?

     

    Chris Yue

    十一月 10, 2012 在 11:46 上午

    我今天看了一下,现在的autoloader.php的确是放在了vendor根目录下面

     

redfire.du

三月 18, 2012 在 9:33 下午

请教博主,为什么我这边老是提示Call to undefined method Symfony\Component\Routing\RequestContext::fromRequest()呢。

    Chris Yue

    三月 21, 2012 在 10:34 上午

    你能提供一下完整的代码吗?

     

发表评论

1 + = 10