本文首发于 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