以前、PHPでパラメータをディレクトリで表現する方法について記事を書きました。
今回実際にこの方法でプログラムを制作することがあったのですが、意外な落とし穴があることがわかりました。
それは、
画像が表示されない。
ということです。
.htaccessはいろいろ便利ですが、使い方を誤ると思いがけないことが起こります。
色々調べて対処できましたので、忘備録として記録いたします。
現象はこのような感じです。
サンプル01のような画像付きのHTMLに、.htaccessで以下のように記述しました。
RewriteEngine on
RewriteRule ^(.*)$ index.html [L]
すると、サンプル02のようになりました。
なぜ?
と頭を抱えますが、いつものごとくググって調べて対処しました。
その結果、サンプル03のように、.htaccess指定をしていても画像が表示されるようになりました。
原因は.htaccessに例外条件を指定していなかったため
.htaccessでディレクトリ指定をパラメータ化するには、.htaccess設置フォルダ以下のURLを全て無視するというような設定をします。
HTML内に記述されている画像にもパスという名のURLが記述されています。
これが無視されるため、画像が表示されなくなるのです。
例えば https://office-obata.com に上記指定をすると、https://office-obata.com/sample.jpg の「/sample.jpg」部分は無視されることになります。
これを何とかするためには、「例外条件」を指定すれば回避できます。
つまり、画像は無視しないようにする条件を.htaccessに記述するのです。
具体的にはどうやればいいの?
.htaccessに例外条件を入れればよいということはわかりましたが、具体的にどう記述すればよいかわかりません。
そもそも、.htaccessの記述方法ってプログラム言語と違いすぎていてさっぱりわかりません。
色々調べて、次のように記述すれば画像が表示されるようになりました。
RewriteEngine on
RewriteCond %{REQUEST_URI} !\.jpg$
RewriteRule ^(.*)$ index.html [L]
RewriteCondを1行足したら、表示されるようになりました。
でも、ここで疑問がわきます。
RewriteCondeって何?
そもそもRewriteRuleってのもそもそも何?
RewriteCondとRewriteRuleの意味
RewriteRule は動作命令
そもそもサーバーは.htaccessに記載された命令を実行します。
その命令にあたる部分が、RewriteRuleです。
.htaccessには、最低限、RewriteRuleがあれば動作します。
RewriteCondは条件指定
これに対し、RewriteCondは条件指定を意味します。
言ってみればif文です。
RewriteRuleの直前に記述し、条件がOKならばRewriteRuleが実行されます。
条件NG(条件に該当しない)場合は、RewriteRuleが実行されません。
なるほど、.htaccessで例外指定とはRewriteCondでの記述を入れるということがわかりました。
それを踏まえて追加した記述を見てみると、何となく意味が分かります。
今回RewriteCondeで、「jpg画像ならば例外」という指定をしています。
具体的には「jpg画像でないならば実行」という条件を記述しています。
RewriteRuleの実行条件に「Jpg画像でないこと」を指定することで、画像を表示されるようにしたのです。
でも、ここでさらに疑問がわきました。
疑問:記号の意味がさっぱり分かりません。
.htaccessには^だの$だのいろいろ記号が使われています。
これが.htaccessのわかりにくさの原因でもあります。
正直私もこの記号の意味が分からなくてさっぱりでした。
今回使用している記号の意味について以下に記述いたします。
他にも記号はありますが、今回は使ったもののみ記述します。
%{REQUEST_URI} | 呼び出されたURLのこと |
! | 条件の反転。if文でいうところの not。 今回の意味だと、「jpg画像ならば偽」→「jpg画像でないなら真」となります。 |
. | 頭の一文字と一致する場合「真」。何か一文字ある場合無条件一致となります。 |
* | 直前の文字と一致する場合「真」。直前の文字と同じものが複数個あってもOKという意味です。 .* と記述すると、ワイルドカード何文字でも一致となるので、事実上すべての記述という意味です。 |
() | 条件のくくりです。if文の条件を()でくくるのと同じ意味です。 |
\(バックスラッシュ) | 命令記号を文字として認識させます。 \.jpgの「.」(ドット)は本来一文字ワイルドカードの意味ですが、ここでは「.jpg」という名称であるかどうか?という意味で使用されています。 |
^ | この記号の直後の文字がURLの先頭にある場合「真」となります。 |
$ | この記号の直前の文字がURLの末尾にある場合「真」となります。 |
\.jpg$ | 末尾の文字が「.jpg」ならば「真」という意味になります。 |
!\.jpg$ | 末尾の文字が「.jpg」でなければ「真」という意味になります。 |
^(.*)$ | 事実上すべての文字という意味になります。 |
RewiteCondは、原則記述されたURLの文字がどのように一致するか?(または一致しないか?)という条件で判定します。
なので、文字列を抽出する意味の記号が多いのです。
注意点:他の画像やファイル、ディレクトリも例外にしたい場合
今回、サンプルではjpg画像のみ例外としていましたが、実際にはgif、png、cssファイル、jsファイル、フォルダなど様々な例外要素があります。
その場合も考慮した場合、以下のように記述します。
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_URI} !(^/フォルダ名/)
RewriteCond %{REQUEST_URI} !\.css$
RewriteCond %{REQUEST_URI} !\.js$
RewriteCond %{REQUEST_URI} !\.jpg$
RewriteCond %{REQUEST_URI} !\.jpeg$
RewriteCond %{REQUEST_URI} !\.gif$
RewriteCond %{REQUEST_URI} !\.png$
RewriteCond %{REQUEST_URI} !\.ico$
RewriteRule ^(.*)$ index.php [L]
例外にするものを順番に並べます。
すべての条件が「真」の場合RewriteRuleが実行されます。
RewriteCondの条件の中で、一つでも該当しないものがあれば、RewriteRuleは実行されません。
無論OR条件のパターンもありますが、今回は割愛します。
画像等のファイル以外にも「フォルダ」を例外にすることもできます。
この場合もフォルダ名を指定すればOKです。
いままで.htaccessは意味がよくわからず使っていましたが、RewriteCondとRewiteRuleの関係が理解できたら、よくわかるようになりました。
大変よい知識を得ることができました。