Drupal .htaccess rewrite 规则分析
Drupal 默认通过 apache 的 mod_rewrite 来实现 Clean URLs 功能,大家可以打开根目录下 .htaccess 看到关于 mod_rewrite 的规则,下面我们来分析一下 Drupal 的 rewrite 规则:
# Various rewrite rules.
<IfModule mod_rewrite.c>
? RewriteEngine on
? # If your site can be accessed both with and without the 'www.' prefix, you
? # can use one of the following settings to redirect users to your preferred
? # URL, either WITH or WITHOUT the 'www.' prefix. Choose ONLY one option:
? #
? # To redirect all users to access the site WITH the 'www.' prefix,
? # (http://example.com/... will be redirected to http://www.example.com/...)
? # adapt and uncomment the following:
? # RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
? # RewriteRule ^(.*)$ http://www.example.com/$1 [L,R=301]
? #
? # To redirect all users to access the site WITHOUT the 'www.' prefix,
? # (http://www.example.com/... will be redirected to http://example.com/...)
? # uncomment and adapt the following:
? # RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
? # RewriteRule ^(.*)$ http://example.com/$1 [L,R=301]
? # Modify the RewriteBase if you are using Drupal in a subdirectory or in a
? # VirtualDocumentRoot and the rewrite rules are not working properly.
? # For example if your site is at http://example.com/drupal uncomment and
? # modify the following line:
? # RewriteBase /drupal
? #
? # If your site is running in a VirtualDocumentRoot at http://example.com/,
? # uncomment the following line:
? # RewriteBase /
? # Rewrite URLs of the form 'x' to the form 'index.php?q=x'.
? RewriteCond %{REQUEST_FILENAME} !-f
? RewriteCond %{REQUEST_FILENAME} !-d
? RewriteCond %{REQUEST_URI} !=/favicon.ico
? RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
</IfModule>
RewriteEngine on 后面的三段,是当站点同时绑定了泛域名 (如 example.com) 和 www. (如 www.example.com) 的时候用的,作用是让它们跳转到同一个域名上,[NC] 是说明判断是否匹配域名 (%{HTTP_HOST}) 时忽略大小写,[L,R=301] 说明是最后的一条 rewrite 规则,并且以 301 响应来强制重定向。
接下来两段是表明 rewrite 的目录,如果 Drupal 放在别名的子目录里面,可以通过设定 RewriteBase 来让 apache 正确 rewrite (很多时候我们并不需要这样做)。
最后一段是正式 (无 # 注释掉) 的 rewrite 规则,!-f 判断文件不存在,!-d 判断目录不存在,!=/favicon.ico 判断访问路径不是 favicon.ico (这里避免了当 favicon.ico 确实不存在于文件系统中而导致的跳转,通常这不是我们想要的),过滤后的 URI 都会通过 rewrite 变成 index.php?q=xxx 这样的形式,[L,QSA] 说明是最后一条 rewrite 规则,QSA 说明在后面追加原有的 GET 串。
下面是 Zend Framework 的 .htaccess 设置:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]
这个是官方文档里提出的 .htaccess 的写法,我已经有几乎一年没有用 ZF 了,记得当年 1.3 版本时的写法很简单的,显然现在进步了不少,是从文件系统上判断,而不是仅仅的正则匹配了。先判断是非空文件 (-s) 或者是一个有效的连接 (-l) 或者是一个目录 (-d) 就执行第一个跳转,这里用了 - 和 [L] 来指明符合上面的都不跳转并退出 rewrite,而其他的 URI 也就会全部 rewrite 到 index.php 了。
然后是 CodeIgniter 的 .htaccess 设置:
RewriteEngine on
RewriteCond $1 !^(index\.php|images|robots\.txt)
RewriteRule ^(.*)$ /index.php/$1 [L]
CI 只是简单的判断了 URI 是否不以表达式里面的字符串开头,如果符合则 rewrite 题到 index.php,就如当年的 ZF。
最后看看 CakePHP 的:
<IfModule mod_rewrite.c>
?? RewriteEngine on
?? RewriteRule??? ^$ app/webroot/??? [L]?
?? RewriteRule??? (.*) app/webroot/$1 [L]?
</IfModule>
Cake 就更低低了,只是 rewrite 到 webroot 目录的对应文件~~~
估计现在大家对众多框架的 rewrite 规则都有了解,ZF 的改进也已经明确的告诉我们怎样做了 :)