4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

PHPでフレームワークとかは使わずにそれっぽいアドレスにしてみたり

Posted at

もう既にタイトルが意味不明ですね…

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)&paramって渡せればよかったので、試行錯誤の末以下のようなRewriteに辿り着いた。(抜粋)

RewriteRule ^(.*user)\/([0-9a-zA-Z_]{1,15})\/? $1.php?screen_name=$2&%{QUERY_STRING} [L]
web.config
              <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>タグなんてちゃんと活用してる人いんの?
結構化石化してそう…
これを使ってパスを分かりにくくするなんていう記事もあったけど…(多分今時のブラウザにはインスペクタがついてるから完全に無駄。)

以上、役に立たないやったことまとめメモでした。読みにくくてごめんなさい!

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?