もう既にタイトルが意味不明ですね…
URLのパラメーターを/で区切って渡したい
こんなことする方法は色々あるかと思います。今回はRewrite先生の力を借りました。ぐぐれば山のように出てくると思うので今回は割愛したかった()
まずそれなりにこいつ(ルーティング)が厄介
あれ、鯖によって書き方が違うのは以前例を示したんですけど、多分この方法でhoge/foo.phpにhoge/foo/aaa/bbb/なんてやろうとすると無限ループが発生してしまい500
エラーを返したり(Apache)そもそもそんなのはマッチしない!ってことで404
を返したり(IIS)するわけです。
どうしろって書いてる記事見つからないんだよこれが…
とりあえず今回は限られたパターンが通せばOK
(既存のページの改造に用いたため、)今回はhoge/user/(screen_name)/?param
ってのをhoge/user.php?screen_name=(screen_name)¶m
って渡せればよかったので、試行錯誤の末以下のようなRewriteに辿り着いた。(抜粋)
RewriteRule ^(.*user)\/([0-9a-zA-Z_]{1,15})\/? $1.php?screen_name=$2&%{QUERY_STRING} [L]
<rule name="user" stopProcessing="true">
<match url="^(.*user)\/([0-9a-zA-Z_]{1,15})\/?" />
<action type="Rewrite" url="{R:1}.php?screen_name={R:2}" appendQueryString="true" />
</rule>
なお、これをやるにあたって@mpywに相談してみたところ、いっそのことパラメーターのパースとか自前でやっちゃえば、とか言われたけどめんどくさいので今回はパス。
ところでこのRewrite、鯖によって仕様の違いが良かったりめんどくさかったり。
両鯖共通してGETクエリ(ブラウザから送られたアドレスの?hoge)は渡されない。
Rewrite後のURLにクエリがついてなかったら自動的に付与される(?)
今回はもちろん?screen_name=$2
ってしてるのでそうはいかず、
hoge/user/(screen_name)/?param
のようにリクエストして受け取ったクエリを見たらparmはついていなかったので、 Apache のRewriteには&%{QUERY_STRING}
を直接当ててやったらうまくいった。
続いて IIS 。こちらはとても親切。シンプルに appendQueryString="true"
がついてるだけで勝手にクエリが追加された。
相対パスの問題
都合上、今回作っていたものは環境によって様々なURIに同じものを置く必要があった。そのためルーティングもそうなってた訳だが、ページ内の内部リンクは全て相対パスになっている。もちろんこのタグを全て置き換えるのは面倒なのだが、それ以前に置き換えてもおかしくなる。
結論から言えば置き換えない
このために便利な<base>
タグがあるんじゃないだろうか。
全てのリンクより(script/cssのlink等含)これを指定してやれば全く今まで通り動く。HTML5
で追加された新要素でもなく昔から存在するタグでもありブラウザ互換の心配もない。
但しそのパスを取得するのに注意が必要かも
dirname($_SERVER["SCRIPT_NAME"])
を使ってやれば目的のpathは取れるのだが、dirname()
はwindows上では/
を\
で返すと言う厄介な性質がある。
str_replace
してやればこの差異は解決。
$path = str_replace("\\", "/", dirname($_SERVER["SCRIPT_NAME"]));
あとはそれがドキュメントルートかどうかで分けてやる(これもdirnameのある意味厄介なところ)
$base_path = $path == "/" ? "/" : $path ."/";
こうして出来上がった$base_path
をヘッダの出来るだけ上(meta charset
を最初に置いておいてその次、ってのがいいっぽい。)で呼び出してやる。
<base href="<?=$path?>" />
お疲れ様でした。
これでやっとこさ変なパス指定が出来ました!
ところで...
<base>
タグなんてちゃんと活用してる人いんの?
結構化石化してそう…
これを使ってパスを分かりにくくするなんていう記事もあったけど…(多分今時のブラウザにはインスペクタがついてるから完全に無駄。)
以上、役に立たないやったことまとめメモでした。読みにくくてごめんなさい!