實作一個小型 Router use PHP (1)
之前有個開發Framework的經驗,在REST的設計風格中,HTTP Method是操作Resource的動作,而URL則是需要操作的Resource本身。所以我們必須讓HTTP Method及URL對應到要執行的程式上,實做Router的需求就這樣產生。那麼以下是不專業的範例教學。
首先建立一個PHP程式 server.php
<?php
// filename: server.php
print_r($_SERVER);
然後我們用curl來發送請求來觀察PHP到底收到了什麼訊息
curl -X GET "localhost/server.php/segement/input" -d "param=test" -G
底下是curl輸出之結果
Array
(
[HTTP_USER_AGENT] => curl/7.21.6 (x86_64-pc-linux-gnu) libcurl/7.21.6 OpenSSL/1.0.0e zlib/1.2.3.4 libidn/1.22 librtmp/2.3
[HTTP_HOST] => localhost
[HTTP_ACCEPT] => */*
[PATH] => /usr/local/bin:/usr/bin:/bin
[SERVER_SIGNATURE] => <address>Apache/2.2.20 (Ubuntu) Server at localhost Port 80</address>
[SERVER_SOFTWARE] => Apache/2.2.20 (Ubuntu)
[SERVER_NAME] => localhost
[SERVER_ADDR] => 127.0.0.1
[SERVER_PORT] => 80
[REMOTE_ADDR] => 127.0.0.1
[DOCUMENT_ROOT] => /var/www/
[SERVER_ADMIN] => webmaster@localhost
[SCRIPT_FILENAME] => /var/www/server.php
[REMOTE_PORT] => 58117
[GATEWAY_INTERFACE] => CGI/1.1
[SERVER_PROTOCOL] => HTTP/1.1
[REQUEST_METHOD] => GET
[QUERY_STRING] => param=test
[REQUEST_URI] => /server.php/segement/input?param=test
[SCRIPT_NAME] => /server.php
[PATH_INFO] => /segement/input
[PATH_TRANSLATED] => /var/www/segement/input
[PHP_SELF] => /server.php/segement/input
[REQUEST_TIME] => 1335154750
)
根據 $_SERVER 的內容中我們挑出能用的部份,REQUEST_METHOD 就是HTTP請求時的Method而 PATH_INFO 、PHP_SELF 及 REQUEST_URI 則可以用來當作比對用的URL。PATH_INFO的內容/segement/input
完全符合需求,另外的 PHP_SELF 及 REQUEST_URI 要做額外的處理才能使用。
還有一件值得一提的事情,上面三個變數Apache都有、Nginx少 PATH_INFO 而IIS則少 REQUEST_URI。
接下來就開始實作了,實做一個Router我們需要上面提到的HTTP Method、URL以及Route Rule及Callback,原理很簡單當Method及URL與Route rule互相Match的時候就會去呼叫Callback執行相對應的動作。首先新增一個名為router的class把一些基本的架構制定出來
<?php
// filename: router.php
class router {
public function __construct() {
$this->method = $_SERVER['REQUEST_METHOD'];
$this->url = $_SERVER['PATH_INFO'];
}
public function add($route, $callback) {
// do something
}
public function run() {
// compare
}
}
以上的class提供一些基本的功能,當class被new時自動取得Method及URL,再用add加入Route Rule及Callback,接來下就可以用run讓Router 跑路 啟動了。
那麼比對怎樣做,直接用 == 字串比對就好啦 比較好的做好是使用正規表達式去比對字串。
待續...