PHPフレームワークはどのようにリクエストされたURLを取得しているか?
自分でフレームワークを作ろうとか思うと、こういった素朴な疑問がでてきたり。昨今のフレームワークはRails以来、URLを解析してコントローラ及びメソッドをコールするというのが主流になってるんじゃないかと思う。そこで各フレームワークの実装を調べてみた。
調べたのは以下のフレームワーク
- Zend Framework 1.8.1
- kohana 1.7.1
- CakePHP 1.2.3.8166
Ztend Framework
<?php // Zend_Controller_Request_Http#setRequestUri if ($requestUri === null) { if (isset($_SERVER['HTTP_X_REWRITE_URL'])) { // check this first so IIS will catch $requestUri = $_SERVER['HTTP_X_REWRITE_URL']; } elseif (isset($_SERVER['REQUEST_URI'])) { $requestUri = $_SERVER['REQUEST_URI']; // Http proxy reqs setup request uri with scheme and host [and port] + the url path, only use url path $schemeAndHttpHost = $this->getScheme() . '://' . $this->getHttpHost(); if (strpos($requestUri, $schemeAndHttpHost) === 0) { $requestUri = substr($requestUri, strlen($schemeAndHttpHost)); } } elseif (isset($_SERVER['ORIG_PATH_INFO'])) { // IIS 5.0, PHP as CGI $requestUri = $_SERVER['ORIG_PATH_INFO']; if (!empty($_SERVER['QUERY_STRING'])) { $requestUri .= '?' . $_SERVER['QUERY_STRING']; } } else { return $this; } } elseif (!is_string($requestUri)) { return $this; } else { // Set GET items, if available if (false !== ($pos = strpos($requestUri, '?'))) { // Get key => value pairs and set $_GET $query = substr($requestUri, $pos + 1); parse_str($query, $vars); $this->setQuery($vars); } }
Zend Framework は「HTTP_X_REWRITE_URL」→「REQUEST_URI」→「ORIG_PATH_INFO」の順番で取得している。おそらくIIS→Apache他→CGIみたいな流れだろうか? 書かれているコメントもそうっぽい。
kohana
<?php // Router_Core#find_uri elseif (isset($_SERVER['PATH_INFO']) AND $_SERVER['PATH_INFO']) { Router::$current_uri = $_SERVER['PATH_INFO']; } elseif (isset($_SERVER['ORIG_PATH_INFO']) AND $_SERVER['ORIG_PATH_INFO']) { Router::$current_uri = $_SERVER['ORIG_PATH_INFO']; } elseif (isset($_SERVER['PHP_SELF']) AND $_SERVER['PHP_SELF']) { Router::$current_uri = $_SERVER['PHP_SELF']; }
kohanaはかなりシンプル。「PATH_INFO」→「ORIG_PATH_INFO」→「PHP_SELF」の順番に取得しようとしている。IISとかこれで大丈夫なのだろうか? と思ったがkohanaのサイトには
An HTTP server. Kohana is known to work with: Apache 1.3+, Apache 2.0+, lighttpd, and MS IIS
installation:requirements [Kohana User Guide]
と書いてあったりするので大丈夫なのだろう。多分。
CakePHP
<?php // dispatcher.php uri foreach (array('HTTP_X_REWRITE_URL', 'REQUEST_URI', 'argv') as $var) { if ($uri = env($var)) { if ($var == 'argv') { $uri = $uri[0]; } break; } }
kohanaに輪をかけてシンプル。「HTTP_X_REWRITE_URL」→「REQUEST_URI」という感じ。argvはCLIなのでここでは省略。IISを気にしなければREQUEST_URIだけとればOKということだろうか?
結論
サーバとPHPの組み合わせでどのようにスーパーグローバル変数が変化するのか、というドキュメントを上手く見つけることができなかったのでどれが正解なのかよくわからない。むむむ…。自分がやるんだったら、REQUEST_URI→PATH_INFO→ORIG_PATH_INFOかなぁ。IISはどうでもいいし。