QeePHP的URL路由解析与生成

blogdaren 2015-01-18 抢沙发 1857人次
路由功能,简单来说就是 URL 重写。

比如我们最初的地址是: http://qeephp.com/index.php?controller=projects&action=show&name=qeephp
经过优化后就是:http://qeephp.com/projects/qeephp

第二个地址相比第一个,不但更短,而且更有意义。也更容易被人记忆,当然对于搜索引擎来说也很友好。

过去要实现这样的功能,我们要做几件事:
1、修改服务器设置,启用 URL 重写功能,例如 Apache 的 mod_rewrite
2、为网站添加重写规则,每一个要重写的 URL 都得添加一次规则
3、在应用程序中编写一个生成 URL 的助手类,并根据一个规则表来生成优化后的网址

麻烦的事情就是如果我们要调整一下 URL 的结构或者新增一些规则,就得改同时修改网站的重写规则配置 文件、助手类。如果要重写的网址数量一多,维护起来就非常不方便了。要是换个运行环境,说不定还不支持 rewrite,或者需要修改所有的重写规则(例如 lighttpd 的规则就和 apache 不同)。

--------------------------------------

为了 解决这个问题,各种新一代的框架都提供了 URL 的路由功能。

URL 路由功能分为两部分:
1、URL 地址的解析
2、URL 地址的生成

URL 地址的解析

URL 解析是把诸如 http://qeephp.com/projects/show/qeephp 这样的地址解析为应用程序需要的参数,这样框架才能知道应该调用哪一个控制器来完成这个请求,并且把参数传递给控制器。

http://qeephp.com/projects/show/qeephp 这个地址在 qeephp.com 上解析后就是:

控制器: projects
动 作: show
参 数: name=qeephp

这样一来在 projects 控制器的 show 动作方法中就可以通过 name 参数判断 用户是要查看哪一个开源项目的信息了。

为了能够解析 http://qeephp.com/projects/qeephp 这样的地址,我们需要在配置文件中添加一条规则:

    projects_show:
      pattern: "/projects/:name"
      defaults:
        controller: "projects"
        action: "show"
      config:
        name: "[a-z0-9\-_]+"

复制代码
projects_show 是这个规则的名字,而 pattern 是规则匹配模式。匹配模式中的 :name 则是一个变量,而该变量通过 config 选项指定了比对规则为“[a-z0-9\-_]+”(name 参数的值只能是字母、数字下划线和横线)。

经过这样设置后, http://qeephp.com/projects/show/qeephp 这样的 URL 就能被正确解析了。

相对于在服务器配置文件中写重写规则,URL 路由提供的规则有几个好处:
1、不需要修改服务器设置的权限,我们只需要修改应用程序的配置文件
2、修改应用程序的设置就可以配置 URL 重写,因此不需要重新启动 Web Server 软件
3、比 Web Server 的重写规则更简单


URL 地址的生成

解决了 URL 的解析问题,还有 URL 的生成问题。

URL 路由提供的生成功能可以根据你提供的参数, 自动匹配合适的规则,然后生成最终的 URL 地址。

例如:
# 生成 /projects/fleaphp
url('projects/show', array('name' => 'fleaphp'))

# 生成 /projects/qeephp
url('projects/show', array('name' => 'qeephp'))

# 生成 /projects/example-todo
url('projects/show', 'name/example-todo')

假如我们有多条规则,Qee PHP 可以自动匹配出最合适那一条,然后生成对应的 URL 地址。

这种能力带来了下列好处:
1、我们再也不需要维护两个规则表了(一个用于解析,一个用于生成),一个规则表就搞定了一切
2、只需要修改规则表,就可以获得不同的 URL 地址,而不需要修改模板、程序中生成 url 的代码
3、只需要修改应用程序的设置,就可以让应用程序工作在不同的服务器环境中,适应各种情况

例如我们把前面的规则改为:

    projects_show:
      regex: '/project-([a-z0-9\-_]+)\.html'
      defaults:
        controller: "projects"
        action: "show"
      config:
        name: 1

复制代码
生成的 URL 地址就会自动变成: http://qeephp.com/project-qeephp.html 这样的。
这种灵活性可以为网站的用户体验、SEO 带来很多便利。

########################### 华丽的分割线 ###########################

SEO 优化

一个网站运营一段 时间后,栏目设置很可能发生变化,此时就有可能导致 URL 变化。而 URL 变化的最大问题就是导致以前的连接失效,对用户体验非常不好,而且也会影响搜索引擎对网站的收录。所以我们必须保证以前的 URL 不失效。

例如以前新闻 页面的网址是 http://my.com/123456.html,而现在是 http://my.com/news/sports/123456.html。对于这种需求,我们利用 URL 路由可以轻松搞定。

先写两个规则:

    # 解析和生成新的新闻页面 URL
    news_page:
      regex: '/news/([a-z]+)/([0-9]+)\.html'
      config:
        category: 1
        news_id:  2
      defaults:
        controller: news
        action:     show
    # 解析老的新闻页面 URL
    news_page_keep_old:
      regex: '/([0-9]+)\.html'
      config:
        news_id:  1
      defaults:
        controller: news
        action:     show

复制代码
上述两条规则,放在前面的优先级更高。

当请求的 URL 是 http://my.com/123456.html 时,前面的规则匹配失败,而后面的规则匹配成功。因此请求送给了 news 控制器的 show 动作方法处理,并且附带 news_id 参数。

[php]
function actionShow()
{
    $news_id = intval($_GET['news_id']);
    $news = News::find($news_id)->get();
   
    ... 显示新闻内容
}
[/php]

这样就保证了原有 URL 的有效性。

那么当请求是 http://my.com/news/sports/123456.html 时,前面的规则就匹配成功,此时就不会再匹配后面的规则。而请求还是 actionShow() 来处理。前面的规则多了一个 category 参数,这里并没有用上,直接忽略即可。但这个参数是必不可少的,会用于后面的 URL 生成。

现在我们来看看模板中生成 URL 的代码:


url('news/show', array(
    'news_id' => $news->id,
    'category' => $news->category_name
))


可以看到,这里我们生成 URL 时使用了 category 参数,因此前面的规则会被用于生成 URL。最终我们会得到类似 http://my.com/news/cars/23343.html 这样的结果。

现在我们已经完美的解决了问题:既保证了以前 URL 的有效性,又让访问者在访问老页面后可以通过页面中的 URL 导航到新格式的 URL 中。

--------------------------------------

URL 随心变

除了 SEO,URL 路由还可以让我们随心所欲的构造 URL 地址。例如 http://qeephp.com/cases/19 这个 URL 规则是:

    cases_show:
      pattern: "/cases/:id"
      defaults:
        controller: "cases"
        action: "show"
      config:
        id: "[0-9]+"

复制代码
我们把规则改为:

    cases_show:
      regex: '/mygod/show\-me\-the\-money/news\-sports\-(\d+)\.html'
      defaults:
        controller: "cases"
        action: "show"
      config:
        id: 1

复制代码
这时 URL 就变成 http://qeephp.com/mygod/show-me-the-money/news-sport-19.html 了。可以说和以前的 URL 简直是两码事。

而这些修改和变化,完全不需要我们修改应用程序中的代码和模板代码,唯一需要改动的就是路有规则表。 

版权声明:除非注明,本文由( blogdaren )原创,转载请保留文章出处。

本文链接:QeePHP的URL路由解析与生成

发表评论:

您的昵称:
电子邮件:
个人主页: