本文首發於 MVC 框架中的路由器(Router)是如何跑起來的,轉載請註明出處。
說明: 貌似 SF 譯文類別出 BUG,因此本文以原創類別給出。php
MVC 路由器(Router)或分發器(Dispatcher)會檢測 HTTP 請求的 URL,並嘗試將單個 URL 組件與控制器和控制器中定義的方法匹配,同時將全部參數傳入方法中。shell
下面給出了一個簡單的路由器類,能夠大體闡明路由器是如何工做的。然而在實際項目中,路由器要比下面的示例路由器複雜不少,由於它必須處理更多的東西。數組
<?php class SimpleRouter { // 路由數組,存儲咱們定義的路由 private $routes; // 這個方法用於將定義的路由加入到 $routes 數組 function add_route($route, callback $closure) { $this->routes[$route] = $closure; } // 執行特定的路由 function execute() { $path = $_SERVER['PATH_INFO']; /** * 檢測給定路由是否被定義, * 或者執行默認的 '/' 首頁路由。 */ if (array_key_exists($path, $this->route)) { $this->route[$path](); } else { $this->route['/](); } } }
SimpleRouter 類是 MVC 路由器的簡化模型。它的主要功能是將用戶定義的每一個路由添加到數組中,並執行它。要理解它是如何工做的,請將下面的代碼複製到 index.php 文件中。瀏覽器
<?php // index.php class SimpleRouter { // 路由數組,存儲咱們定義的路由 private $routes; // 這個方法用於將定義的路由加入到 $routes 數組 function add_route($route, callback $closure) { $this->routes[$route] = $closure; } // 執行特定的路由 function execute() { $path = $_SERVER['PATH_INFO']; /** * 檢測給定路由是否被定義, * 或者執行默認的 '/' 首頁路由。 */ if (array_key_exists($path, $this->route)) { $this->route[$path](); } else { $this->route['/](); } } } /* 建立 Router 實例 */ $router = new SimpleRouter(); /* 添加首頁閉包值路由器 */ $router->add_route('/', function(){ echo 'Hello World'; }); /* 添加另外一個閉包路由 */ $router->add_route('/greetings', function(){ echo 'Greetings, my fellow men.'; }); /* 添加可回調函數做爲路由 */ $router->add_route('/callback', 'myFunction'); /* 回調函數處理程序 */ function myFunction(){ echo "This is a callback function named '" . __FUNCTION__ ."'"; } /* 執行路由 */ $router->execute();
如今到瀏覽器訪問下列 url:安全
http://localhost/index.php/ http://localhost/index.php/greetings http://localhost/index.php/callback
對於每一個 url,你應該會看到在咱們的路由中定義的不一樣消息。那麼路由器是如何工做的呢?閉包
在咱們的示例中,add_route 方法將 url 的路徑名(route)添加到路由數組,而且定義對應的處理操做。這個處理操做能夠是一個簡單的函數或者回調函數,做爲閉包傳入。如今當咱們執行路由器的 execute 方法時,它會檢測在當前 $routes 數組中是否匹配到路由,若是有,則執行這個函數或回調函數。mvc
若是你使用 var_dump 這個 $routes 數組,你能夠看到數組的具體內容。對於每一個定義的路由都存儲一個閉包與其關聯。框架
array (size=3) '/' => object(Closure)[2] '/greetings' => object(Closure)[3] '/callback' => string 'myFunction' (length=10)
執行處理由如下幾行完成。$this->routes[$path]** 語句返回一個閉包,該閉包保存在 **\$routes 數組中,用於指定路由的執行,注意語句結尾處的 ()。函數
$this->routes[$path](); // 或 $this->routes['/']();
上面的示例簡單地演示了路由器的工做原理,爲了簡單起見,咱們沒有處理任何錯誤,也沒有考慮路由的安全性問題。this