PHP フレームワーク Router.php 作成 (1)

2018年5月8日

みなさんこんにちは!タカモリです。
今日もいつもどおり暇なので、phpの勉強に勤しんでいるわけですが、日々新しいことに気づく毎日で、ほんとにプログラミングっていうのは奥が深いなぁ、なんていうことを感じているところです。
早く一人前のプログラマーになって、webサイト作りてーーー!!

というわけで今日も前回の続きをやっていく!
本日はRouterクラスの作成についてだ!
Routerクラスっていうのは、まぁなんていうかあれだ、あれルーティングってやつを制御するクラスだ。
はっきり言って結構むずい。

これが実はフレームワークの中で俺が一番興味があったクラスなのだ。
何故かと言うと、俺のブログを初めから見ている人は知っているかもしれないが、俺がフレームワークに手を出したきっかけが、動的にページを作成していくという目的のなかでフレームワークという方法を見つけたからなのだ。

逆に言えば、それ以外はおまけの知識みたいな感じだ。
とは言いながらもフレームワークを勉強したおかげでかなりphpについての知識も格段にアップし、今まで以上にプログラミングについて興味がでてきたので結果オーライである。

そもそもフレームワークには縁が無いものと思っていたので、まさかこんなに早くフレームワークを勉強することになるとは思ってもいなかった。

と前置きはこのへんにしておいて、さっそくsrcを貼ってみる。

勉強の為、すでに一番上の箇所でインスタンス化してある。

このクラスでは、2つのメソッドが用意されている。「__construct()メソッド」、「compileRoutes()メソッド」と「resolve()メソッド」だ。

・__construct()メソッド

このクラスに限った話ではないが、クラスに__construct()というメソッドを用意することで、このRouterクラス自体の初期化みたいなことができる。コンストラクトとは、このクラスがインスタンスされた時点で最初に呼ばれる関数のことで、この場合は__construct($definitions)の引数に$aという引数を渡し、更に後に説明するcompileRoutes()メソッドに$aをそのまま引数で渡した後、処理されて得た値を$routesプロパティに代入している。

・compileRoutes()メソッド

続いては、__construct()で呼ばれた、このメソッドの役割を簡潔に話してみたいと思う。

このメソッドでは、後に実装するルーティング定義配列から、動的に変更される部分について正規表現で扱える形に変更するというものだ。

安心してほしい。初めて聞く人にとってはこの説明が全く意味のわからない説明であることは理解している。

俺もこの意味を解読する為に何時間費やしたかわからない。というか今でも自信はない!

ルーティング定義配列とは、ユーザーから指定されたurlに従って、このコントローラーの、このアクションで応対する。というのを予め定めている、2次元の連想配列だ。

ここで言うコントローラーとは、クラスを差し、アクションとはメソッドのことを差す。

つまり、このurlが指定された場合に、このクラスのこのメソッドで応対する為のものと言う風になるだろうか。

文章で説明するのは正直かなり面倒くさいので、実際の挙動を見てみよう。

パーフェクトphpでは、後に実装することになるルーティング定義配列を先取りし、変数$aに格納している。

この後どういう流れになるかというと、先ほども伝えたとおり、__construct()でさっそく呼ばれたcompileRoutes()メソッドには引数で$aが渡されている。その後は2次元配列$aのキーの部分「’/’」や「’/status/post’」などの部分を、explode()関数でスラッシュ毎に分割した配列を作る。[0]=>status・[1]=>postというような感じだ。引数のltrim関数というのがわからなければググってみてくれ。「lite・trim」すなわち右を切り取る・整えるなどという意味だ。

このメソッドにおいて大事なのはここから!

先ほどexplode()関数で$urlをスラッシュ毎に分割した際に、もし先頭が「:」コロンの場合、「:user_name」や「:id」など。

この場合は「:」以外の文字列を抜取り、それを$nameに代入した後、更に'(?P<‘ . $name . ‘>[^/]+)’みたいな形で、$nameを変な記号で囲っている。

これが、一番最初に説明した、動的に変更される部分について、正規表現で扱える形に変更ということなのだ。

正規表現とは、ん~~~~なんと言えばよいか。

超大雑把にいうと、自分の扱いやすい形にそのデータを変更すること!という風になるか。

まぁ、今は正規表現はあまり関係がないので、適当に流してほしい。

あくまで正規表現で扱える形に変更しただけだ。

どう変更したのかというと、後に正規表現では、自分の欲しいデータに変更する際に、配列形式で値を取得することができるのだが、その際に?P<○○>という形を指定しておくとその配列を添字配列ではなく、連想配列として値を取得することができるようになるのだ。

詳しくは「正規表現 名前付き キャプチャ」などでググってみてくれ。

では、その右にある[^/]+これはなんなのか??

これが正規表現で実際に取得する値なのだ。[]の中にある^については否定の意味。+については一回以上繰り返す。という意味だ。

おそらくこれは、スラッシュ以外の文字列ということになる。ということは、後ほど正規表現で取得したい値はスラッシュ意外の文字列で、それを連想配列で格納する際のキーが$nameなのだ。

つまり、先頭にコロンがついたurlの部品(:user_name)については、そのコロン以外の文字を後ほど連想配列のキーとする。ということがやりたい訳だ。

スラッシュ以外の文字列の取得については、このメソッドでは関係がなく、後ほど正規表現を行う時に必要なので、その準備と言ったところか。

話は長くなったが、先ほどのsrcを実行してみよう。

これが実行結果なのだが、確かに先ほどコロンがついていた箇所のみ変な文字に変わっている。

ん?んんん?あれ?おかしい。さっきの俺の説明ではコロンがついているところは、コロン以外の文字を後ほど連想配列のキーとしたい為、本来であれば(?P<user_name >[^/]+)のような形になるはずだ!

それに比べてなんだこの(?P[^/]+)みたいな省略系は!!!

かなり実はこれでつまづいて、srcと睨めっこしていたのだが、それは無意味なのであった。実はphpは出力する際に<>のような記号があると、htmlタグと判断しこれを出力しない仕様になっている。つまり不正防止の機能だ。その為この中の文字が一切表示されなかったのだ。

では、これをどうすれば表示させることができるか。

多分何個か方法はあるが、今回はhtmlspecialchars()関数を仕様して、タグを文字列として出力させてみる。

その際なのだが、htmlspecialchars()関数は配列に仕様できないので、今回は適当にできそうな場所を選んでhtmlspecialchars()関数を使ってみた。

ここで$tokenにしっかり値が入っているか確認してみると

うん、実際にはこのように<>の中にコロン以外の文字列が入っていることがわかる。

ということで、今回はここまでだ。今回の処理では後に使う正規表現への下準備の処理であるということであることがわかった。

次回はこれを用いて正規表現を実際に扱う、resolve()メソッドについて進めたいと思う。