2009-12-24
mod_rewriteでGETパラメータ名を変更する。
mod_rewriteのお話。
旧システムから新システムの以降など、システムの仕様が変わる時でも古いURLを引き継ぎたい場合に役に立つ小技。
問題1
GETパラメータの名前aaaをbbbに変更したい場合はどのようにすれば良いか?
誤
ついつい以下のように設定してしまうかと思いますが、うまく動きません。
RewriteRule filename.html\?aaa=(.*) filename.html?bbb=$1 [L]
正
RewriteCondを使い、QUERY_STRINGの条件を指定すると、うまく動きます。
RewriteCond %{QUERY_STRING} aaa=(.+) RewriteRule filename.html filename.html?bbb=%1 [L]
%1で、RewriteCondでマッチしたパターンを取得できる。
問題2
GETパラメータの名前aaaをbbbに変更したいが、aaa以外のパラメータはそのまま残したい場合はどのようにすれば良いか?
解答1
QSAをつける。
RewriteCond %{QUERY_STRING} aaa=(.+) RewriteRule filename.html filename.html?bbb=%1 [L,QSA]
aaa=○○&ccc=△△だった場合、bbb=○○&aaa=○○&ccc=△△のように、古いパラメータもそのままついてしまう。
解答2
以下の場合、aaaのみbbbに書き換える事ができる。
RewriteCond %{QUERY_STRING} ^(.*)aaa=(.+)$ RewriteRule filename.html filename.html?%1bbb=%2 [L]
オマケ
『上記試してみましたが、うまく動きません!』という場合
上から順に評価されるので、こんな事しているとうまく動かない。
#ファイルが存在する場合はそれを表示する RewriteCond %{REQUEST_FILENAME} -f [OR] RewriteCond %{REQUEST_FILENAME} -d RewriteRule ^.* - [L] # ↑ファイルが存在した時点で、上記が評価されて終わってしまう。 #パラメータ名を書き換える。 RewriteCond %{QUERY_STRING} ^(.*)aaa=(.+)$ RewriteRule filename.html filename.html?%1bbb=%2 [L]
順番を変更する事でうまく動く。
#パラメータ名を書き換える。 RewriteCond %{QUERY_STRING} ^(.*)aaa=(.+)$ RewriteRule filename.html filename.html?%1bbb=%2 [L] #↑先に評価される。 #ファイルが存在する場合はそれを表示する RewriteCond %{REQUEST_FILENAME} -f [OR] RewriteCond %{REQUEST_FILENAME} -d RewriteRule ^.* - [L]
そんな感じで、お役に立てれば幸いです。
関連記事
[Apache][mod_rewrite]続:存在するファイルはスルーしたい
The Definitive Guide to Apache Mod_rewrite (Definitive Guides)
- 作者: Rich Bowen
- 出版社/メーカー: Apress
- 発売日: 2006/02/20
- メディア: ハードカバー
- クリック: 32回
- この商品を含むブログ (3件) を見る
Apacheクックブック 第2版 ―Webサーバ管理者のためのレシピ集
- 作者: Ken Coar,Rich Bowen,笹井崇司
- 出版社/メーカー: オライリージャパン
- 発売日: 2008/09/26
- メディア: 大型本
- 購入: 6人 クリック: 144回
- この商品を含むブログ (30件) を見る
2009-06-07
続:存在するファイルはスルーしたい
mod_rewriteのお話。
以前に書いた挙動の疑問が解決したので再掲載。
ファイルが存在する場合はそのファイルを表示し、存在しない場合はindex.phpを表示するようにしたい。
よくある例が以下のようになっているが、実際にはうまく動かない。
RewriteEngine on RewriteBase / #ファイルが存在しない且つ、ディレクトリが存在しない場合は、index.phpを表示 RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^$ /index.php [L,QSA] RewriteRule ^(.*)$ /index.php?jb=$1 [L,QSA]
上記の例がなぜうまく動かないかというと、RewriteCondは直下のRewriteRuleにしか通じないのです。
つまり、存在するファイルに対して、
RewriteRule ^(.*)$ /index.php?jb=$1 [L,QSA]
のルールが適応されてしまうことになります。
これを回避する為の解決策は下記の例の通りです。
解決策1:RewriteRuleの順番を変える
上記の例では順番を変えることで解決します。
RewriteEngine on RewriteBase / RewriteRule ^$ /index.php [L,QSA] #ファイルが存在しない且つ、ディレクトリが存在しない場合は、index.phpを表示 RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ /index.php?jb=$1 [L,QSA]
解決策2:RewriteRule毎に、RewriteCondを書く
RewriteRule毎に、RewriteCondを1つ1つ書くことで回避できます。
RewriteEngine on RewriteBase / #^$用のRewriteCondとRewriteRule RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^$ /index.php [L,QSA] #^(.*)$用のRewriteCondとRewriteRule RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ /index.php?jb=$1 [L,QSA]
解決3:存在するファイルに対してRewriteRuleを先に適応する
先に存在するファイルに対してルールを適応してしまう。
こっちの方が楽かもしれません。
RewriteEngine on RewriteBase / #ファイルが存在するか、ディレクトリが存在する場合は、そのファイルを表示する RewriteCond %{REQUEST_FILENAME} -f [OR] RewriteCond %{REQUEST_FILENAME} -d RewriteRule ^.* - [L] #ファイルが存在しない場合に以下のルールを適用 RewriteRule ^$ /index.php [L,QSA] RewriteRule ^(.*)$ /index.php?jb=$1 [L,QSA]
解決策4:ルールを良く見直す。
実は、.*を.+に変えるだけで、1行目のルールは必要なかったりします。
途中で気がついたのですが、説明が書けなくなるので最後に回しました。
RewriteEngine on RewriteBase / #ファイルが存在しない且つ、ディレクトリが存在しない場合は、index.phpを表示 RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.+)$ /index.php?jb=$1 [L,QSA]
そんな感じで、RewriteCondは直下のRewriteRuleにのみ適用されます。
RewriteRuleを書く時は、後から見る人が勘違いしないように一行あけて書くようにしましょう。
関連記事
[Apache][mod_rewrite]存在するファイルはスルーしたい
The Definitive Guide to Apache Mod_rewrite (Definitive Guides)
- 作者: Rich Bowen
- 出版社/メーカー: Apress
- 発売日: 2006/02/20
- メディア: ハードカバー
- クリック: 32回
- この商品を含むブログ (3件) を見る
Apacheクックブック 第2版 ―Webサーバ管理者のためのレシピ集
- 作者: Ken Coar,Rich Bowen,笹井崇司
- 出版社/メーカー: オライリージャパン
- 発売日: 2008/09/26
- メディア: 大型本
- 購入: 6人 クリック: 144回
- この商品を含むブログ (30件) を見る
2009-02-07
存在するファイルはスルーしたい
mod_rewriteのお話。
ファイルが存在する場合はそのファイルを表示し、存在しない場合はindex.phpを表示するようにしたい。
よくある例が以下のようになっているが、実際にはうまく動かない。
RewriteEngine on RewriteBase / #ファイルが存在しない且つ、ディレクトリが存在しない場合は、index.phpを表示 RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^$ /index.php [L,QSA] RewriteRule ^(.*)$ /index.php?jb=$1 [L,QSA]
修正(2009/06/07)
挙動について解決しました。
[Apache][mod_rewrite]続:存在するファイルはスルーしたい
以下のように書くと期待通りに動作する。
RewriteEngine on RewriteBase / #ファイルが存在するか、ディレクトリが存在する場合は、そのファイルを表示する RewriteCond %{REQUEST_FILENAME} -f [OR] RewriteCond %{REQUEST_FILENAME} -d RewriteRule ^.* - [L] #ファイルが存在しない且つ、ディレクトリが存在しない場合は、index.phpを表示 RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^$ /index.php [L,QSA] RewriteRule ^(.*)$ /index.php?jb=$1 [L,QSA]
これで目的は達成されるのだが、最初の例でなぜうまくいかないかが納得いかない。
この挙動について説明できる方がおられれば、ご教授いただけると幸いです。
The Definitive Guide to Apache Mod_rewrite (Definitive Guides)
- 作者: Rich Bowen
- 出版社/メーカー: Apress
- 発売日: 2006/02/20
- メディア: ハードカバー
- クリック: 32回
- この商品を含むブログ (3件) を見る
Apacheクックブック 第2版 ―Webサーバ管理者のためのレシピ集
- 作者: Ken Coar,Rich Bowen,笹井崇司
- 出版社/メーカー: オライリージャパン
- 発売日: 2008/09/26
- メディア: 大型本
- 購入: 6人 クリック: 144回
- この商品を含むブログ (30件) を見る
2008-02-07 時間の大切さ
Apacheで多くのサブドメインをDBで管理するモジュール
http://blog.livedoor.jp/pri1231/archives/50077277.html
mod_vdbh?を使うと可能らしい。
今度試してみよう。


