一个网站运营一段时间后,栏目设置很可能发生变化,此时就有可能导致 URL 变化。而 URL 变化的最大问题就是导致以前的连接失效,对用户体验非常不好,而且也会影响搜索引擎对网站的收录。所以我们必须保证以前的 URL 不失效。
例如以前新闻页面的网址是 http://msplinks.com.cn/MDFodHRwOi8vbXkuY29tLzEyMzQ1Ni5odG1s,而现在是 http://msplinks.com.cn/MDFodHRwOi8vbXkuY29tL25ld3Mvc3BvcnRzLzEyMzQ1Ni5odG1s。对于这种需求,我们利用 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://msplinks.com.cn/MDFodHRwOi8vbXkuY29tLzEyMzQ1Ni5odG1s 时,前面的规则匹配失败,而后面的规则匹配成功。因此请求送给了 news 控制器的 show 动作方法处理,并且附带 news_id 参数。
- function actionShow()
- {
- $news_id = intval($_GET['news_id']);
- $news = News::find($news_id)->get();
- ... 显示新闻内容
- }
这样就保证了原有 URL 的有效性。
那么当请求是 http://msplinks.com.cn/MDFodHRwOi8vbXkuY29tL25ld3Mvc3BvcnRzLzEyMzQ1Ni5odG1s 时,前面的规则就匹配成功,此时就不会再匹配后面的规则。而请求还是 actionShow() 来处理。前面的规则多了一个 category 参数,这里并没有用上,直接忽略即可。但这个参数是必不可少的,会用于后面的 URL 生成。
现在我们来看看模板中生成 URL 的代码:
- url('news/show', array(
- 'news_id' => $news->id,
- 'category' => $news->category_name
- ))
可以看到,这里我们生成 URL 时使用了 category 参数,因此前面的规则会被用于生成 URL。最终我们会得到类似 http://msplinks.com.cn/MDFodHRwOi8vbXkuY29tL25ld3MvY2Fycy8yMzM0My5odG1s 这样的结果。
现在我们已经完美的解决了问题:既保证了以前 URL 的有效性,又让访问者在访问老页面后可以通过页面中的 URL 导航到新格式的 URL 中。
--------------------------------------
URL 随心变
除了 SEO,URL 路由还可以让我们随心所欲的构造 URL 地址。例如 http://msplinks.com.cn/MDFodHRwOi8vcWVlcGhwLmNvbS9jYXNlcy8xOQ== 这个 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://msplinks.com.cn/MDFodHRwOi8vcWVlcGhwLmNvbS9teWdvZC9zaG93LW1lLXRoZS1tb25leS9uZXdzLXNwb3J0LTE5Lmh0bWw= 了。可以说和以前的 URL 简直是两码事。
而这些修改和变化,完全不需要我们修改应用程序中的代码和模板代码,唯一需要改动的就是路有规则表。