美文网首页
PHP解析PATH_INFO模式URL的路由类

PHP解析PATH_INFO模式URL的路由类

作者: 许文同学 | 来源:发表于2018-02-20 17:28 被阅读0次

    编码工作中框架给我们提供了很多便利,自己更多处理的是业务层的代码,而很少接触较为基础的东西。
    趁最近有空,自己想着写了一个处理PATH_INFO模式URL的路由类。因为自己工作常用框架是TP5,所以有些风格习惯定义和TP5很像。
    完整DEMO请参阅我的码云:https://gitee.com/VwenX/Router
    下面是路由部分核心类,URL解析后用反射API处理参数然后调用对应方法。

    
    // 定义常量
    define('URL_PATH',isset($_SERVER['PATH_INFO']) ? preg_replace('/\/+/','/',strtolower($_SERVER['PATH_INFO'])) : '/');
    define('APP_PATH', 'app');
    define('Control_PATH', 'controller');
    
    class Route
    {
        
        // 路由规则
        private static $rules = [
                            'get'     => [],
                            'post'    => [],
                            'put'     => [],
                            'delete'  => [],
                            '*'       => []
                        ];
        /**
         * 绑定路由
         * @param  string $rule  路由规则
         * @param  string $route 路由地址
         * @param  string $type  请求类型
         * By.Vwen https://gitee.com/VwenX/Router
         */
        static function rule($rule, $route = '', $type = '*')
        {
            $rule = strtolower($rule);
            $rule = '/'==substr($rule,0,1) ? $rule : '/'.$rule;
            $route = strtolower($route);
            $type = strtolower($type);
            if ('*' == $type) {
                foreach (self::$rules as $key => $value) {
                    self::$rules[$key][$rule] = $route;
                }
            }else{
                self::$rules[$type][$rule] = $route;
                self::$rules['*'][$rule] = $route;
            }
        }
        /**
         * 提供快捷绑定
         * 如 Route::get() Route::post()
         * 仅为概念简写,实际应用请按需修改及验证
         */
        static function __callStatic($func, $arguments)
        {
            $arguments[] = $func;
            self::rule(...$arguments);
        }
        /**
         * 解析当前请求URL
         * @return array    路由信息数组
         */
        static function parseUrl()
        {
            $analysis = ['status'=>404];
            $METHOD = strtolower($_SERVER['REQUEST_METHOD']);
            // 直接匹配
            if (isset(self::$rules[$METHOD][URL_PATH])) {
                $analysis['status'] = 200;
                $analysis['rule'] = URL_PATH;
                $analysis['route'] = self::$rules[$METHOD][URL_PATH];
            }else{
            // 列表匹配
                foreach (self::$rules[$METHOD] as $rule => $route) {
                    if (substr($rule,-1)=='$' && substr_count($rule,'/')!=substr_count(URL_PATH,'/')) {
                            continue ;
                    }
                    $reg = '/^'.str_replace('/','\/',preg_replace('/:[a-z]+(?=\/|\$|$)/','\S+',$rule)).'/';
                    if (!preg_match($reg,URL_PATH)) {
                        continue ;
                    }
                    $analysis['status'] = 200;
                    $analysis['rule'] = $rule;
                    $analysis['route'] = $route;
                    break;
                }
            }
            // 处理未注册的路由 /M/C/A
            if (!isset($analysis['route'])) {
                $path_list = explode('/', trim( URL_PATH,'/'));
                $module = isset($path_list[0]) ? $path_list[0] : 'index';
                $Controller = isset($path_list[1]) ? $path_list[1] : 'index';
                $action = isset($path_list[2]) ? $path_list[2] : 'index';
                $analysis['rule'] = $analysis['route'] = '/'.$module.'/'.$Controller.'/'.$action;
            }
            // 获取路由参数
            if (isset($analysis['route'])) {
                $param = [];
                $rule_list = explode('/', $analysis['rule']);
                $path_list = explode('/', URL_PATH);
                if(strpos($analysis['rule'], ':')!==false){
                    foreach ($rule_list as $key => $value) {
                        if (substr($value,0,1)==':') {
                            $param[trim($value,':$')] = $path_list[$key];
                        }
                    }
                }
                // 获取剩余参数
                for ($i=count($rule_list); $i < count($path_list); $i+=2) { 
                    if (isset($path_list[$i+1])) {
                        $param[$path_list[$i]] = $path_list[$i+1];
                    }
                }
                $analysis['param'] = self::Params($param);
                // 在控制器方法传参中用 $req 获取请求参数
                $analysis['param']['req'] = $analysis['param'];
            }
            return $analysis;
        }
        /**
         * 处理请求参数
         * @param  array $param    PATH_INFO参数
         * @return array    
         */
        static function Params($param=[])
        {
            return array_merge($param,$_GET,$_POST);
        }
        /**
         * 生成URL
         * @param  string $route  路由地址 模块/控制器/方法
         * @param  array  $vars   参数数组
         * @param  string $method 按特定请求模式解析
         * @return string    处理好的URL
         */
        static function getUrl($route='',$vars=[],$method='*')
        {
            $route = strtolower(trim($route,'/'));
            $method = strtolower($method);
            $rule = array_search($route,self::$rules[$method]);
            if (!$rule) {
                return '';
            }
            $rule_list = explode('/', trim($rule,'/'));
            // 处理预定义参数
            if (strpos($rule, ':')!==false) {
                foreach ($rule_list as $key => $value) {
                    if (strpos($value, ':')!==false) {
                        $rule_list[$key] = isset($vars[trim($value,':$')]) ? $vars[trim($value,':$')] : '';
                        if (isset($vars[trim($value,':$')])) unset($vars[trim($value,':$')]);
                    }
                }
            }
            // 处理剩余参数
            if (strpos($rule, '$')==false && $vars != '') {
                foreach ($vars as $key => $value) {
                    $rule_list[] = $key;
                    $rule_list[] = $value;
                }
            }
            $rule = rtrim('/'.implode('/',$rule_list),'$');
            return $rule;
        }
    }
    

    相关文章

      网友评论

          本文标题:PHP解析PATH_INFO模式URL的路由类

          本文链接:https://www.haomeiwen.com/subject/ufpgtftx.html