2008年4月24日 星期四

[野人獻曝]Apache上的Mod_rewrite的實作說明(上)

Rewrite

最近不小心沉迷在研究Apache的mod_rewrite,
剛好也有點心得,
所以寫篇簡單心得放在這裡吧。

其實一切都是因為我從Cakephp裡的.htaccess得到一些靈感開始的,
所以我就以Cakephp的rewrite方法來作點說明吧!

首先看到Cakephp根目錄下的.htaccess檔吧:

<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^$ app/webroot/ [L]
RewriteRule (.*) app/webroot/$1 [L]
</IfModule>


第一行和最後一行基本上算是必備,
所以不用問太多加下去就對了XD

第二行開始,代表著你要啟用RewriteEngine的功能,
這一行必加,因為不加的話,你也不會知道為啥你的rewrite無效~

第三、四行則代表要把所有的Request導向給app/webroot,
換言之,Cakephp根目錄下的index.php基本上是擺好玩的!

既然前面提到已經被導向至app/webroot了,
那麼就繼續看app/webroot/.htaccess的內容吧:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
</IfModule>


第一行、第二行和最後一行內容跟前段相同,所以就不多說了,
比較有意思的是第三、四、五行。
其意義如下:

  • RewriteCond %{REQUEST_FILENAME} !-d
    意義:任何附掛的字串都不會被視為一個目錄
    比如你輸入http://localhost/cakephp/a/s/d,(cakephp是你放cakephp檔案的目錄)
    那麼rewrite將會把a/s/d當成一般字串,而不會繼續去尋找cakephp下是不是有目錄a、目錄s。


  • RewriteCond %{REQUEST_FILENAME} !-f
    意義:任何附掛的字串都不會被視為一個檔案
    比如你輸入http://localhost/cakephp/a/s/d.css,(cakephp是你放cakephp檔案的目錄)
    那麼rewrite將會把a/s/d當成一般字串,而不會繼續去尋找cakephp下是不是有目錄a、目錄s、或是檔案d.css。

  • RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
    以上所提到的附掛字串都被當成一個參數,其名稱為url,
    指派給這個目錄下的index.php(就是app/webroot/index.php啦)處理。
    注意後面的[QSA,L],
    QSA(Querystring appedned)代表著要附掛Querystring給index.php,
    至於L(Last)代表最後一條rewrite規則。

6 則留言:

旭彥 提到...

讚!讚!夠實用!
我也正巧在survey cakePHP,
正為其導向規則搞得暈頭轉向. :P
這篇文章使我茅塞頓開呀。

Faryne 提到...

其實很多框架大致上都是用這樣的導向規則,所以把這一套學會了,大概其他框架的導向規則就不難了XD

旭彥 提到...
作者已經移除這則留言。
旭彥 提到...
作者已經移除這則留言。
旭彥 提到...

抱歉, 之前的回應在表達上有不流暢的地方, 我修飾一下重貼。^^!

< IfModule mod_rewrite.c >
RewriteEngine On

# 條件一: %{REQUEST_FILENAME} 不是目錄。
# (換言之: 若 %{REQUEST_FILENAME} 是目錄, 則不符合條件)
RewriteCond %{REQUEST_FILENAME} !-d

# 條件二: %{REQUEST_FILENAME} 不是檔案。
# (換言之: 若 %{REQUEST_FILENAME} 是檔案, 則不符合條件)
RewriteCond %{REQUEST_FILENAME} !-f

# 以上兩個條件都必須成立: "%{REQUEST_FILENAME} 不是目錄 且 不是檔案", 才套用RewriteRule.

# 否則, 若無其它限制的話, 就是依照一般的存取規則來存取目錄或檔案了。這點可以透過url連結一個已存在的目錄或檔案來進行驗證。

# QSA代表QueryString Appended的意思,L是Last,在此的意義是最後一條RewriteRule。
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]

# 由於L的作用, 後續若有RewriteRule,也不再繼續套用了。
< /IfModule >

以上註解若有錯誤, 敬請指正。 ^^!

Faryne 提到...

雖然不知道你為什麼刪除文章,不過還是回一下好了!

基本上你沒錯,我的講法確實有點問題,
這是因為我有時候會故意講錯一些東西,
讓看我東西的人不會只把我的作品整個囫圇吞棗下去~(當然有很多時候真的是我打錯)!

總之,你有發現我文章中的問題,
也算是您比我厲害了XDD!
(頭一次碰到可以吐我嘲的人)