<?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)系统自定义函数调用事先写好的操作中自定义的函数方法。