路由类,实现url到类方法的映射

原创 2019-02-09 10:51:03 322
摘要:route.php <?php /**  * 路由解析类  * 1.路由解析  * 2.请求分发  */ namespace pig; class Route {     //路由配置信息     protected&nbs
route.php
<?php
/**
 * 路由解析类
 * 1.路由解析
 * 2.请求分发
 */
namespace pig;
class Route
{
    //路由配置信息
    protected $route = [];
    //PATHINFO
    //public $pathInfo = [];
    protected $pathInfo = [];
    //URL参数
    protected $params = [];
    //public $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];
            //二个参数:模块和控制器自定义,操作默认
            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);
                //print_r($arr);die;
                //键值必须成对出现,所以每次递增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()====$route->parse();$route->worm();
        return $this;
    }
    //请求分发
    public function dispatch()
    {
        //生成带有命名空间的控制器类名称:app\模块\controller\控制器类
        //类名称应该与类文件的所对应的绝对路径一一对应,这样才可以实现自动映射,
        //方便自动加载
        //模块名称
        $module = $this->pathInfo['module'];
        //控制器名称
        $controller = '\app\\' . $module . '\\controller\\' . ucfirst($this->pathInfo['controller']);
        //die($controller);
        //操作名
        $action = $this->pathInfo['action'];
        //die($action);
        if (!method_exists($controller, $action)) {
            $action = $this->route['action'];
            header('Location: /');
        }
        //将用户的请求分发到指定的控制器和对应的操作方法上
        return call_user_func_array([new $controller, $action], $this->params);
    }
        //获取pathInfo
        public function getPathInfo()
        {
            return $this->pathInfo;
        }
        //获取模块
        public function getModule()
        {
            return $this->pathInfo['module'] ? : $this->route['module'];
        }
        //获取控制器名称
        public function getController()
        {
            return '\app\\'.$this->getModule().'\\controller\\'.ucfirst($this->pathInfo['controller']);
        }
}
//测试路由
$queryStr = $_SERVER['QUERY_STRING'];
echo '<hr>';
$config = require 'config.php';
$route = new Route($config['route']);
$route->parse($queryStr);
//print_r($route->pathInfo);
//print_r($route->params);
//测试请求分发(空间得加载)
require __DIR__.'/../app/admin/controller/Index.php';
require __DIR__.'/../app/admin/controller/User.php';
echo $route->dispatch();

控制器类:

<?php
/**
 * 要加载的控制器类
 */
namespace app\admin\controller;
class User
{
    public function show()
    {
        echo '我是user控制器中的show方法';
    }
}

总结:路由解析类实现路由解析和请求分发,路由解析就是从url请求中的提取出模块,控制器,方法以及参数,分别存放在数组中,请求分发实现将提取的信息与路径一一对应,实现自动映射,也即将信息组装成可以访问的地址。注意,要实现自动加载,必须首先加载访问的命名空间。

运行结果:

路由.png

批改老师:韦小宝批改时间:2019-02-11 10:00:22
老师总结:写的很不错 路由在一个框架中起到很大的一个重要 它关系到我们框架的安全性等

发布手记

热门词条