使用mod_rewrite或像PHP这样的语言来处理友好/干净/漂亮的URL会更好吗?

我正在开发我的第一个大小适中的PHP站点,对于在应用程序中处理干净/友好/漂亮的URL的“正确方法”(假设曾经有这样的事情)我有点困惑。

我看到的方式有两个主要选项(我将以简化的社交新闻网站为例):

1.使用mod_rewrite处理所有可能的URL。 这看起来与以下类似,但不完全相同:

RewriteRule ^article/?([^/]*)/?([^/]*)/?([^/]*) /content/articles.php?articleid=$1&slug=$2 RewriteRule ^users/?([^/]*)/?([^/]*) /content/users.php?userid=$1&username=$2 RewriteRule ^search/?([^/]*)/? /content/search.php?query=$1 

2.把一切传给一些处理程序脚本,让它担心细节:

 RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule (.*) handler.php?content=$1 

显然这都是未经testing的“空码”,但你明白了。

  • 这两种方式之一会比其他方式慢吗? 据推测,mod_rewrite比较慢,因为我将被迫为此使用.htaccess文件。
  • 这两种方法都有严重的缺点吗?
  • 这种事情有没有“最佳做法”,还是每个开发人员都倾向于自己决定? 我知道WordPress使用选项二(虽然这是比我值得调查究竟是如何做的更麻烦)。

选项1 (.htaccess和几个.php文件)经常被“过去”使用; 现在,我看到选项2 (每个请求通过一个.php文件)使用了更多。

我在选项2中看到的主要优点是:

  • 您可以添加/修改任何类型的URL,而无需更改任何物理文件,如.htaccess
    • 这意味着URL的格式可以在应用程序的管理部分配置
  • 你只有一个入口点到你的PHP代码。
    • 这意味着一切都通过index.php :如果你需要为所有请求执行一些代码,把它放在那里,你肯定会永远执行。
    • 例如,这在MVC框架中使用了很多。

几年前,我会选择1; 现在我使用MVC和框架,我总是选择2。

真的这是“值得使用的框架?” 问题在变相。

使用mod_rewrite来定义你的URL路由是快速和容易的(如果你理解正则表达式…),但是你的应用程序代码不知道URL,除非你在某处重复信息。

通常,人们多次复制这些信息而不考虑这些信息,在视图中的链接或重定向中对网址进行硬编码。 这真是太麻烦了,如果决定在开发过程中改变网站的网址结构,总有一天会让人感到痛苦。 你一定会错过一个,并在某个地方结束404。

在您的应用程序中使用路由组件(例如Symfony中的路由组件)意味着您可以将名称附加到路由,从而允许您定义一次URL并多次重复使用它们:

 # apps/frontend/config/routing.yml homepage: url: / param: { module: default, action: index } 

这使得很容易链接到您的网站的网页,而不必重复自己:

 <?php echo url_for('@homepage') ?> 

使用选项#2 – 为什么? .htaccess中的RewriteRules是强大的工具,但它们是某种静态的 。 我的意思是你不能轻松管理,然后使用PHP(或任何你要使用)。 另外.htaccess并没有提供太多的灵活性,但有一些优点(例如:速度更快)。

选项#2也需要.htaccess你注意到,但在大多数情况下, RewriteRule采取以下形式:

 RewriteRule (.\*) index.php 

其中index.php是你的前端控制器。

这种灵活性的最大优点(IMO)是每个路由用PHP(或者你使用的)来描述,所以访问这些路由,修改它们要容易得多。 此外,这些路由不仅可用于将URL更改为一组变量,还可以相反的方式 – 从一组变量创建URL。

我想下面的例子(从Symfony框架)将解释我在说什么:

 // apps/.../config/routing.yml - Describes routing rules post: url: /read/:id/:slug params: { module: blog, action: index } requirements: { id: \d+, slug: \w+ } // apps/.../modules/blog/templates/indexSuccess.php - template for index action <?php echo link_to($post['title'], '@post?id=' . $post['id'] . '&slug=' . $post['slug']); ?> //creates: <a href="/read/123/my-first-blog-post.html">My first blog post</a> 

现在无论何时你改变你的rounting.yml文件,并将/read/:id/:slug改成/:slug_:id你在应用程序中的所有链接都会变成/my-first-blog-post_123.html

在使用选项#2时做这样或那样的事情要容易得多。

据我所知,这些方法之间的任何可能的性能差异真的很小,只适用于真正的高流量站点。

我认为没有“最佳做法”,两种方法同样经常使用。 如果你的项目结构允许它,而且你在家里用PHP解析URL(你的项目的其余部分),把所有东西都放在一个控制器文件中,让你的应用程序处理剩下的东西。

如果性能真的是真正的本质,我怀疑有Apache处理地址更快,因为之间没有解释的语言。 (虽然我没有这方面的硬数据)。 但正如我所说,你可能最好从长远来看选择哪一个最能维持。

干净漂亮的网址似乎是由基于PHP脚本的流行内容管理系统Drupal使用.htaccess中的modrewrite规则和插件PHP Drupal模块(如path和pathauto)组合提供的。

鉴于这个工具的成功和普及,以及它运行在最温和的共享主机上的能力,我认为这将是你的答案。