[apache] mod_rewriteの動きをちゃんと理解してみる

Pocket
LINEで送る
[`evernote` not found]

URL

photo credit: jeffsmallwood via photopin cc


なんとなくhttpd.confや.htaccessにmod_rewriteの定義を書いていました。
書いていたといっても、設定例をコピペしている程度でした。
今回はPHPの「codeigniter」フレームワークの設定を行っている際にだいぶはまったので、忘れないように備忘録です。

Index

 

codeigniterのフォルダ構成

codeigniterは公式サイトからモジュールをダウンロードしました。
ダウンロードしたZipファイルの中から以下のフォルダのみ開発用のフォルダへコピーしました。

  • applicationフォルダ
  • systemフォルダ
  • index.php

コピー後に必要なファイルを作成し、最終的に以下の構成となりました。

codeigniter
 +– application
 |  +– controllers
 |  |  +– hoge.php (※1)
 |  +– views
 |  |  +– hoge.php (※2)
 |  +– (その他フォルダはデフォルトのまま)
 +– htdocs (※3)
 |  +– css (フォルダ)
 |  +– images (フォルダ)
 |  +– js (フォルダ)
 |  +– index.php (※4)
 +– system

※1.サンプル用のhogeコントローラークラスになります。
※2.サンプル用のhogeビュークラスになります。
※3.新規にフォルダを作成しました。
※4.ダウンロードしたモジュールに含まれていたindex.phpの場所を移動しました。

このあたりのフォルダ構成については以下のページを参考にしています。
非常に丁寧に書かれているので参考になると思います。
参考:軽量PHPフレームワーク ‘CodeIgniter’ 徹底ガイド!
 

httpd.confの定義

他の開発定義が既にhttpd.confに書かれているため、今回はVirtualHostで記載をしました。

<VirtualHost hoge.com>
  ServerName hoge.com
  DocumentRoot "D:/CodeIgniter/htdocs"
  DirectoryIndex index.php index.html
  <Directory "D:/CodeIgniter/htdocs">
    AllowOverride All
  </Directory>
</VirtualHost>

mod_rewriteの定義は.htaccessで記述するため、「AllowOverride All」の記述が必要です。
※これを書かないと.htaccessが動きません。
 

.htaccessの定義

codeigniterではサンプル用に追加したhogeコントローラへアクセスするために、変換前のURLでアクセスを行うのですが、index.phpを隠す(?)ためにmod_rewriteによって変換しています。

変換前:http://hoge.com/index.php/hoge
変換後:http://hoge.com/hoge

実際の.htaccessの記述は以下になります。

RewriteEngine on
RewriteCond $1 !^(index\.php|images|css|js|robots\.txt|favicon\.ico)
RewriteRule ^(.*)$ index.php/$1 [L]

1行目でmod_rewriteの変換をONにしています。
2行目で変換対象外の条件を記述しています。
以下は変換の対象外となります。

  • index.phpファイル
  • robots.txtファイル
  • favicon.icoファイル
  • cssフォルダ
  • imagesフォルダ
  • jsフォルダ

3行目では2行目の変換対象条件に該当した場合の変換ルールを記述しています。
通常ですと「D:/CodeIgniter/htdocs/hoge」のファイルを探しに行きますが、以下のようにドキュメントルートとパスの間に「index.php」が挿入されます。

http://hoge.com/index.php/hoge

これで設定は完了です。
ブラウザから「http://hoge.com/hoge」へアクセスして、アンプル用に作成したViewクラスの内容が表示されれば成功です。
 

mod_rewriteのデバッグ

自分はここでちゃんと動かなくてはまってしましました・・・
なぜ動かないのかを調べるためにmod_rewriteはデバッグモードがあります。

httpd.confに「RewriteLog」と「RewriteLogLevel」の記述を追加します。

<VirtualHost hoge.com>
  ServerName hoge.com
  DocumentRoot "D:/CodeIgniter/htdocs"
  DirectoryIndex index.php index.html

  RewriteLog "D:/logs/codeigniter-rewrite.log"
  RewriteLogLevel 9

  <Directory "D:/CodeIgniter/htdocs">
    AllowOverride All
  </Directory>
</VirtualHost>

この結果ログを見て、記述設定がループしていることがわかり修正することで直りました。
誤:RewriteCond $1 !^/(index\.php|images|css|js|robots\.txt|favicon\.ico)
正:RewriteCond $1 !^(index\.php|images|css|js|robots\.txt|favicon\.ico)
※!^の後にスラッシュが入っていました。
 

実際の動きの整理

正しく動くようになったmod_rewriteのログは以下です。

[hoge.com/sid#9154f8][rid#93fb28/initial] (3) [perdir D:/CodeIgniter/htdocs/] strip per-dir prefix: D:/CodeIgniter/htdocs/hoge -> hoge
[hoge.com/sid#9154f8][rid#93fb28/initial] (3) [perdir D:/CodeIgniter/htdocs/] applying pattern '^(.*)$' to uri 'hoge'
[hoge.com/sid#9154f8][rid#93fb28/initial] (4) [perdir D:/CodeIgniter/htdocs/] RewriteCond: input='hoge' pattern='!^(index\\.php|img|css|js|robots\\.txt|favicon\\.ico)' => matched
[hoge.com/sid#9154f8][rid#93fb28/initial] (2) [perdir D:/CodeIgniter/htdocs/] rewrite 'hoge' -> 'index.php/hoge'
[hoge.com/sid#9154f8][rid#93fb28/initial] (3) [perdir D:/CodeIgniter/htdocs/] add per-dir prefix: index.php/hoge -> D:/CodeIgniter/htdocs/index.php/hoge
[hoge.com/sid#9154f8][rid#93fb28/initial] (2) [perdir D:/CodeIgniter/htdocs/] strip document_root prefix: D:/CodeIgniter/htdocs/index.php/hoge -> /index.php/hoge
[hoge.com/sid#9154f8][rid#93fb28/initial] (1) [perdir D:/CodeIgniter/htdocs/] internal redirect with /index.php/hoge [INTERNAL REDIRECT]
[hoge.com/sid#9154f8][rid#947b08/initial/redir#1] (3) [perdir D:/CodeIgniter/htdocs/] add path info postfix: D:/CodeIgniter/htdocs/index.php -> D:/CodeIgniter/htdocs/index.php/hoge
[hoge.com/sid#9154f8][rid#947b08/initial/redir#1] (3) [perdir D:/CodeIgniter/htdocs/] strip per-dir prefix: D:/CodeIgniter/htdocs/index.php/hoge -> index.php/hoge
[hoge.com/sid#9154f8][rid#947b08/initial/redir#1] (3) [perdir D:/CodeIgniter/htdocs/] applying pattern '^(.*)$' to uri 'index.php/hoge'
[hoge.com/sid#9154f8][rid#947b08/initial/redir#1] (4) [perdir D:/CodeIgniter/htdocs/] RewriteCond: input='index.php/hoge' pattern='!^(index\\.php|img|css|js|robots\\.txt|favicon\\.ico)' => not-matched
[hoge.com/sid#9154f8][rid#947b08/initial/redir#1] (1) [perdir D:/CodeIgniter/htdocs/] pass through D:/CodeIgniter/htdocs/index.php
[hoge.com/sid#9154f8][rid#985b38/subreq] (3) [perdir D:/CodeIgniter/htdocs/] strip per-dir prefix: D:/CodeIgniter/htdocs/hoge -> hoge
[hoge.com/sid#9154f8][rid#985b38/subreq] (3) [perdir D:/CodeIgniter/htdocs/] applying pattern '^(.*)$' to uri 'hoge'
[hoge.com/sid#9154f8][rid#985b38/subreq] (4) [perdir D:/CodeIgniter/htdocs/] RewriteCond: input='hoge' pattern='!^(index\\.php|img|css|js|robots\\.txt|favicon\\.ico)' => matched
[hoge.com/sid#9154f8][rid#985b38/subreq] (2) [perdir D:/CodeIgniter/htdocs/] rewrite 'hoge' -> 'index.php/hoge'
[hoge.com/sid#9154f8][rid#985b38/subreq] (3) [perdir D:/CodeIgniter/htdocs/] add per-dir prefix: index.php/hoge -> D:/CodeIgniter/htdocs/index.php/hoge
[hoge.com/sid#9154f8][rid#985b38/subreq] (2) [perdir D:/CodeIgniter/htdocs/] strip document_root prefix: D:/CodeIgniter/htdocs/index.php/hoge -> /index.php/hoge
[hoge.com/sid#9154f8][rid#985b38/subreq] (1) [perdir D:/CodeIgniter/htdocs/] internal redirect with /index.php/hoge [INTERNAL REDIRECT]

initial:条件の判定に関するログ
initial>redir :条件該当によりファイル参照先が変換された内容のログ
subreq : ???

どうやら「subreq」はhttpd.confへ「DirectoryIndex」を定義していると処理されるようです。
パスだけ入力した際に、後ろへ「index.html」などを付ける処理ですね。

今回は.htaccessへmod_rewriteの記述をしました。
この記述をhttpd.confに書いた場合少し動きが違います。

RewriteEngine on
RewriteCond $1 !^/(index\.php|img|css|js|robots\.txt|favicon\.ico)
RewriteRule ^(.*)$ /index.php/$1 [L]

2行目と3行目のパス指定の前にスラッシュが入っています。
ログを見ると以下のようになっています。

[hoge.com/sid#8f1550][rid#915b30/initial] (2) init rewrite engine with requested uri /hoge
[hoge.com/sid#8f1550][rid#915b30/initial] (3) applying pattern '^(.*)$' to uri '/hoge'
[hoge.com/sid#8f1550][rid#915b30/initial] (4) RewriteCond: input='/hoge' pattern='!^/(index\\.php|img|css|js|robots\\.txt|favicon\\.ico)' => matched
[hoge.com/sid#8f1550][rid#915b30/initial] (2) rewrite '/hoge' -> '/index.php//hoge'
[hoge.com/sid#8f1550][rid#915b30/initial] (2) local path result: /index.php//hoge
[hoge.com/sid#8f1550][rid#915b30/initial] (2) prefixed with document_root to D:/CodeIgniter/htdocs/index.php/hoge
[hoge.com/sid#8f1550][rid#915b30/initial] (1) go-ahead with D:/CodeIgniter/htdocs/index.php/hoge [OK]
[hoge.com/sid#8f1550][rid#91bb48/subreq] (2) init rewrite engine with requested uri /hoge
[hoge.com/sid#8f1550][rid#91bb48/subreq] (3) applying pattern '^(.*)$' to uri '/hoge'
[hoge.com/sid#8f1550][rid#91bb48/subreq] (4) RewriteCond: input='/hoge' pattern='!^/(index\\.php|img|css|js|robots\\.txt|favicon\\.ico)' => matched
[hoge.com/sid#8f1550][rid#91bb48/subreq] (2) rewrite '/hoge' -> '/index.php//hoge'
[hoge.com/sid#8f1550][rid#91bb48/subreq] (2) local path result: /index.php//hoge
[hoge.com/sid#8f1550][rid#91bb48/subreq] (2) prefixed with document_root to D:/CodeIgniter/htdocs/index.php/hoge
[hoge.com/sid#8f1550][rid#91bb48/subreq] (1) go-ahead with D:/CodeIgniter/htdocs/index.php/hoge [OK]

.htaccessは絶対パスに対して判定処理や書き換えが入っているのに対して、httpd.confに記述した場合は相対パスになっているのがわかります。
初めて動き方を調べてみましたが、ちゃんと理解できれば色々わかってきますね~
 

参考サイト

codeigniter公式サイト : http://ellislab.com/codeigniter
codeigniter guide : http://www.ci-guide.info/

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

この記事のトラックバック用URL