摘要:<?php /** * 路由解析类 * 1.路由解析 * 2.请求分发 */ namespace pig; class Route { //路由配置信息 protected $route
<?php
/**
* 路由解析类
* 1.路由解析
* 2.请求分发
*/
namespace pig;
class Route
{
//路由配置信息
protected $route = [];
//PATHINFO
protected $pathInfo = [];
//URL参数
protected $params = [];
public function __construct($route)
{
//路由配置初始化
$this->route = $route;
}
//解析路由
public function parse($queryStr = '')
{
// /admin/user/add/name/peter/age/30
// $this->pathInfo = ['module'='admin','controller'='user','action'=>'add'}
// 参数数组:$this->params = ['name'=>'peter','age'=>30]
// 第一步:将查询字符串前后的/去掉,再按分隔符/拆分到数组中
$queryStr = trim(strtolower($queryStr),'/');
$queryArr = explode('/',$queryStr);
$queryArr = array_filter($queryArr);
// 第二步:解析出queryArr数组中的内容(模块,控制器,操作,参数)
switch (count($queryArr)){
//没有参数,则使用默认的模块/控制器/操作
case 0:
$this->pathInfo = $this->route;
break;
//只有一个参数:用户只提供了模块,控制器和操作使用默认值
case 1:
$this->pathInfo['module'] = $queryArr[0];
break;
//二个参数:模块和控制器自定义,操作是默认的
case 2:
$this->pathInfo['module'] = $queryArr[0];
$this->pathInfo['controller'] = $queryArr[1];
break;
//三个参数:模块/控制器/操作全部自定义:全部来自用户的实际请求
case 3:
$this->pathInfo['module'] = $queryArr[0];
$this->pathInfo['controller'] = $queryArr[1];
$this->pathInfo['action'] = $queryArr[2];
break;
//对参数进行处理
default:
$this->pathInfo['module'] = $queryArr[0];
$this->pathInfo['controller'] = $queryArr[1];
$this->pathInfo['action'] = $queryArr[2];
//从pathInfo数组的索引3开始,将剩余的元素全部做为参数进行处理
$arr = array_slice($queryArr,'3');
//键值对必须是成对出现,所以每次递增为2
for($i = 0;$i < count($arr);$i += 2){
//如果没有第二个参数,则放弃
if(isset($arr[$i+1])){
$this->params[$arr[$i]] =$arr[$i+1];
}
}
break;
}
//返回当前路由的实例对象,主要是方便链式调用:$route->parse()->worm()->print()
return $this;
}
//请求分发
public function dispatch()
{
//生成带有命名空间的控制器类名称:app\模块\controller\控制器类
//类名称应该与类文件所在的绝对路径一一对应,这样才可以实现自动映射,方便自动加载
//模块名称
$module = $this->pathInfo['module'];
//控制器名称
$controller = 'app\\'.$module.'\controller\\'. ucfirst($this->pathInfo['controller']);
//操作名
$action = $this->pathInfo['action'];
if (!method_exists($controller,$action)){
$action = $this->route['action'];
header('Location:/');
}
// 将用户的请求分发到指定的控制器和对应的操作方法上
return call_user_func_array([new $controller,$action],$this->params);
}
路由类主要实现2个功能,路由解析和请求分发
路由解析首先要从url地址中获取$queryStr = $_SERVER['QUERY_STRING'],再将$queryStr解析成2个部分,模块、控制器、操作为一组,参数为另一组。请求分发就是将模块、控制器重新组合成新的路径,和操作、参数一起使用call_user_func_array([new $controller,$action],$this->params)系统自定义函数调用事先写好的操作中自定义的函数方法。
批改老师:天蓬老师批改时间:2019-04-28 08:48:41
老师总结:如果能理解了这个路由原理, 那么所有框架的底层也不难理解了, 原理都是一样的, 只是实现的机制和复杂程序不同罢了