PHP解析PATH_INFO模式URL的路由類

編碼工作中框架給我們提供了很多便利,自己更多處理的是業(yè)務(wù)層的代碼,而很少接觸較為基礎(chǔ)的東西。
趁最近有空,自己想著寫了一個(gè)處理PATH_INFO模式URL的路由類。因?yàn)樽约汗ぷ鞒S每蚣苁荰P5,所以有些風(fēng)格習(xí)慣定義和TP5很像。
完整DEMO請參閱我的碼云:https://gitee.com/VwenX/Router
下面是路由部分核心類,URL解析后用反射API處理參數(shù)然后調(diào)用對應(yīng)方法。


// 定義常量
define('URL_PATH',isset($_SERVER['PATH_INFO']) ? preg_replace('/\/+/','/',strtolower($_SERVER['PATH_INFO'])) : '/');
define('APP_PATH', 'app');
define('Control_PATH', 'controller');

class Route
{
    
    // 路由規(guī)則
    private static $rules = [
                        'get'     => [],
                        'post'    => [],
                        'put'     => [],
                        'delete'  => [],
                        '*'       => []
                    ];
    /**
     * 綁定路由
     * @param  string $rule  路由規(guī)則
     * @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()
     * 僅為概念簡寫,實(shí)際應(yīng)用請按需修改及驗(yàn)證
     */
    static function __callStatic($func, $arguments)
    {
        $arguments[] = $func;
        self::rule(...$arguments);
    }
    /**
     * 解析當(dāng)前請求URL
     * @return array    路由信息數(shù)組
     */
    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;
        }
        // 獲取路由參數(shù)
        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];
                    }
                }
            }
            // 獲取剩余參數(shù)
            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 獲取請求參數(shù)
            $analysis['param']['req'] = $analysis['param'];
        }
        return $analysis;
    }
    /**
     * 處理請求參數(shù)
     * @param  array $param    PATH_INFO參數(shù)
     * @return array    
     */
    static function Params($param=[])
    {
        return array_merge($param,$_GET,$_POST);
    }
    /**
     * 生成URL
     * @param  string $route  路由地址 模塊/控制器/方法
     * @param  array  $vars   參數(shù)數(shù)組
     * @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,'/'));
        // 處理預(yù)定義參數(shù)
        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,':$')]);
                }
            }
        }
        // 處理剩余參數(shù)
        if (strpos($rule, '$')==false && $vars != '') {
            foreach ($vars as $key => $value) {
                $rule_list[] = $key;
                $rule_list[] = $value;
            }
        }
        $rule = rtrim('/'.implode('/',$rule_list),'$');
        return $rule;
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容