【PHP】フロントコントローラとルーティングの話 その1

おはようございます。

次は、「フロントコントローラとルーティング」について勉強していきたいと思います。
※【パーフェクトPHP】P.207「フロントコントローラと.htaccess」より

フロントコントローラ

フロントコントローラとは、すべてのリクエストを1つのPHPファイルで受け取るようにするものです。
具体的には、

http://hogehoge.com/index.php/login
http://hogehoge.com/index.php/post
http://hogehoge.com/index.php/edit
http://hogehoge.com/index.php/list

などのURLでのアクセスをまずは一旦1つのPHPファイル(フロントコントローラ)にアクセスをするように指定します。(一般的には「index.php」に指定するのが多いみたいです)
そのフロントコントローラで受けた後、適切なアクションで処理を行います。

これらの制御は「.htaccess」ファイルで設定を行います。

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteRule ^(.*)$ index.php [QSA,L]
</IfModule>

ここでは、指定されたファイルが存在する場合はそのファイルを読み込み、存在しなければどんなURLでもすべて「index.php」にアクセスするように制御しています。

例えば、「http://hogehoge.com/login」というURLにアクセスされた場合、「login」というファイルが無ければ「http://hogehoge.com/index.php/login」にアクセスした状態と同じとなります。

ベースURLとPATH_INFO

フレームワーク上でURLを扱う上で、大きく分けて2つの情報「ベースURL」と「PATH_INFO」を制御する方法があります。

ベースURL
ベースURLとは、ホスト部分より後ろから、フロントコントローラまでの値を指します。
(ベースURLは一般的な名称ではなく、パーフェクトPHP内での名称です)

PATH_INFO
PATH_INFOはベースURLより後ろの値となります。
※但しGETパラメータ(foo?bar=)の部分は含みません。

<?php
/*知らなかった関数など
 *strpos::文字列内の部分文字列が最初に現れる場所を見つける
 */
class Request{

  public function getBaseUrl(){

    $script_name = $_SERVER['SCRIPT_NAME'];
    $request_uri = $_SERVER['REQUEST_URI'];

    if(0 === strpos($request_uri, $script_name)){
      //フロントコントローラがURLに含まれる場合
      return $script_name;
    }elseif(0 === strpos($request_uri, dirname($script_name))){
      //フロントコントローラが省略されている場合
      return rtrim(dirname($script_name), '/');
    }
    return '';
  }

  public function getPathInfo(){

    $base_url = $this->getBaseUrl();
    $request_uri = $_SERVER['REQUEST_URI'];

    if(false !== ($pos = strpos($request_uri, '?'))){
      //GETパラメータを削除
      $request_uri = substr($request_uri, 0, $pos);
    }

    //REQUEST_URIからベースURLを取り除く
    $path_info = (string)substr($request_uri, strlen($base_url));

    return $path_info;
  }
}
?>


今日は、「フロントコントローラ」・「ベースURL」・「PATH_INFO」について勉強していきました。
これらによって、どのURLにアクセスされたのかが自動的に判定されます。
次は、「ベースURL」と「PATH_INFO」を利用してルーティングについて定義していきたいと思います。


/*————————————————————————————————————*/
まだ、フレームワークを使った開発の経験は無いですが、この「フロントコントローラ」を利用してアクセスされたURLでルーティングし、対応するコントローラーとアクションメソッドを呼び出すというのが一般的のようです。
※まだ、このパーフェクトPHP内でのフレームワークと勉強中のfuelPHPしか知らない身ですが。。。

おそらく、このルーティングの部分でつまづく人が多いのではないかなと思っています。
(自分がつまづいていた部分であるということもありますが。)

でも、このルーティングの部分を活用すればかなりロジック部とデザイン部の分離ができるし、長々としたURL(http://hogehoge.com/?aid=1&bid=2&cid=3)からも解放されてスッキリ書くことができるようになります。

http://hogehoge.comは便宜上のテキトーなアドレスですので、アクセス先については全く知らないところですのでご注意ください。

ご一読頂きまして、ありがとうございました。



参考記事
パーフェクトPHP

パーフェクトPHP (PERFECT SERIES 3)

パーフェクトPHP (PERFECT SERIES 3)