用php做一个简易的路由

index.php

复制代码
<?php
echo '<pre>$_REQUEST<br>';

print_r($_REQUEST);
// print_r($_SERVER);
 
$path_info = $_SERVER['PATH_INFO'];
$REQUEST_URI = $_SERVER['REQUEST_URI'];

// echo '$path_info='.$path_info;
// echo '$REQUEST_URI='.$REQUEST_URI;

$real_url = $_REQUEST['real_url'] ?? '';
$real_url = trim($real_url, '/');

$arr_url = explode('/', $real_url);
 

echo '<br>$real_url='.$real_url.'<br>arr_url=';
print_r($arr_url);

echo '<br>==========================================<br>';
$routes = [
    'about' => 'AboutController@index',
    'user/get/{username}' => 'UserController@get',
    'user/set/{user_id}' => 'UserController@set',
    'user/del/{user_id}' => 'UserController@del',
    'user/add' => 'UserController@add'
]; 

echo '路由表<br>';
print_r($routes);

echo '<br>==========================================<br>';

$controllerName = $arr_url[0];
$controllerNameLow = strtolower($controllerName);
 
$t_ok_path = '';
$t_ok_router =  '';

foreach($routes as $route_path => $t_router_controller){

    // echo '$route_path='.$route_path.', $t_router_controller='.$t_router_controller.'<br>';

    $arr_route_path = explode('/', $route_path);

    // print_r($arr_route_path); 

    $t_is_match = true;

    foreach($arr_route_path as $path_idx => $t_path){
        // echo "第{$path_idx}段路径<br>";
        $t_lower_path = strtolower($t_path);
        $t_seg_url = $arr_url[$path_idx];
        $t_seg_url_low = strtolower($t_seg_url);
     
        $is_dyn_param = strpos($t_path, '{') !== false;
        if($is_dyn_param){
            continue;
        }

        if($t_lower_path != $t_seg_url_low){
            $t_is_match = false; 
            // echo $t_lower_path . ':'. $t_seg_url_low . '不匹配<br>';
            break; 
        } 
    }

    if(!$t_is_match){
        continue;
    }else{
        $t_ok_path = $route_path;
        $t_ok_router =  $t_router_controller;
        // echo '匹配到路径 = ' .$t_ok_path.', router='. $t_ok_router.'<br>';
        break;
    }
}

if(!$t_ok_path){
    $t_msg = "<br><h1 style='color:red; font-weight:bold;'>404 not found: {$controllerName}</h1>";
    exit($t_msg);
}

echo '匹配到路径 = '.$t_ok_path.'<br>';
echo '匹配到控制器 = '.$t_ok_router.'<br>';
 
$arr_ok_router = explode('@', $t_ok_router);
$realControllerName = $arr_ok_router[0];

$actionName = $arr_ok_router[1];
if(!$actionName){
    $actionName = 'index';
}

$arr_path = explode('/', $t_ok_path);

 $arr_param = [];
foreach($arr_path as $path_idx => $t_path){
    $t_val = $arr_url[$path_idx] ?? '';
    //动态参数
    if(strpos($t_path, '{') !== false 
        && strpos($t_path, '}') !== false){
        $t_param_name = trim($t_path, '{}');
       
        $arr_param[$t_param_name] =  $t_val;
    }else{
    //    $arr_param[] =  $t_val;
    }
}
 
if($arr_param){
    $arr_param = [$arr_param];
}else{
    $t_count = count($arr_path);

    $arr_param = array_slice($arr_url, $t_count+1);
}

echo ' $arr_param =';
print_r( $arr_param );

include_once "controller/{$realControllerName}.class.php";
$t_controller  = new $realControllerName();
call_user_func_array([$t_controller, $actionName], $arr_param);

controller/UserController.class.php

复制代码
<?php

class UserController  {
    public function index() {
          echo 'index user';
    }

   public function get($v_param) {
        echo '<pre><h1 style="color:blue;">in UserController.get()</h1> '; 
        echo '<br>v_param<br>';
        print_r($v_param);
        // echo '<br>_REQUEST<br>';
        // print_r($_REQUEST);

        // $v_name = $_REQUEST['name'] ?? '';
        $v_name = $v_param['username'] ?? '';
        $v_name = trim($v_name);

        if(!$v_name){
            exit('username为空');
        }
        $arr_user = [
            'msk' => ['name'=>'马斯克', 'prop'=>'CEO'],
            'lxn' => ['name'=>'罗西尼', 'prop'=>'CFO'],
            'wzy' => ['name'=>'王志远', 'prop'=>'CTO'],
            'zxy' => ['name'=>'张晓宇', 'prop'=>'COO'],

        ];

        $user_info = $arr_user[$v_name] ?? [];
        if(!$user_info){
            $t_msg = "<div style='color:red'>不存在用户: {$v_name}</div>";
            exit($t_msg);
        }

        echo '用户详情:' . print_r($user_info,1);
   
    }
    public function set($v_param) {
        echo '<pre><h1 style="color:blue;">in UserController.set()</h1>'; 
        echo '<br>v_param<br>';
        print_r($v_param);
    
        $v_user_id = $v_param['user_id'] ?? '';
        $v_user_id = trim($v_user_id);

        echo '用户id:' . $v_user_id;
    }
}

controller/AboutController.class.php

复制代码
<?php

class AboutController  {
    public function index() {
        echo '这是关于页面' . PHP_EOL;

    }

}

nginx的配置:

复制代码
server {
        listen        80;
        server_name  www.myroute.cn;
        root   "D:/php_projects/myroute";
        location / {
            index index.php index.html error/index.html;
            error_page 400 /error/400.html;
            error_page 403 /error/403.html;
            error_page 404 /error/404.html;
            error_page 500 /error/500.html;
            error_page 501 /error/501.html;
            error_page 502 /error/502.html;
            error_page 503 /error/503.html;
            error_page 504 /error/504.html;
            error_page 505 /error/505.html;
            error_page 506 /error/506.html;
            error_page 507 /error/507.html;
            error_page 509 /error/509.html;
            error_page 510 /error/510.html;
            include D:/php_projects/myroute/nginx.htaccess;
            autoindex  off;
        }
        location ~ \.php(.*)$ {
            fastcgi_pass   127.0.0.1:9002;
            fastcgi_index  index.php;
            fastcgi_split_path_info  ^((?U).+\.php)(/?.+)$;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            fastcgi_param  PATH_INFO  $fastcgi_path_info;
            fastcgi_param  PATH_TRANSLATED  $document_root$fastcgi_path_info;
            include        fastcgi_params;
        }
}

D:/php_projects/myroute/nginx.htaccess

复制代码
try_files $uri $uri /index.php?real_url=$uri&$args;

如果是用apache, 则.htaccess内容:

复制代码
<IfModule mod_rewrite.c>
    RewriteEngine On

    # 如果请求的不是一个真实存在的文件
    RewriteCond %{REQUEST_FILENAME} !-f
    # 如果请求的不是一个真实存在的目录
    RewriteCond %{REQUEST_FILENAME} !-d
    # 将请求重写到 index.php,并传递 real_url 和原有的查询字符串
    RewriteRule ^(.*)$ index.php?real_url=/$1 [QSA,L]
</IfModule>

跑一下 : http://www.myroute.cn/user/get/lxn

复制代码
$_REQUEST
Array
(
    [real_url] => /user/get/lxn
)

$real_url=user/get/lxn
arr_url=Array
(
    [0] => user
    [1] => get
    [2] => lxn
)

==========================================
路由表
Array
(
    [about] => AboutController@index
    [user/get/{username}] => UserController@get
    [user/set/{user_id}] => UserController@set
    [user/del/{user_id}] => UserController@del
    [user/add] => UserController@add
)

==========================================
匹配到路径 = user/get/{username}
匹配到控制器 = UserController@get
 $arr_param =Array
(
    [0] => Array
        (
            [username] => lxn
        )

)
in UserController.get()
 
v_param
Array
(
    [username] => lxn
)
用户详情:Array
(
    [name] => 罗西尼
    [prop] => CFO
)

http://www.myroute.cn/user/set/lxn

复制代码
$_REQUEST
Array
(
    [real_url] => /user/set/lxn
)

$real_url=user/set/lxn
arr_url=Array
(
    [0] => user
    [1] => set
    [2] => lxn
)

==========================================
路由表
Array
(
    [about] => AboutController@index
    [user/get/{username}] => UserController@get
    [user/set/{user_id}] => UserController@set
    [user/del/{user_id}] => UserController@del
    [user/add] => UserController@add
)

==========================================
匹配到路径 = user/set/{user_id}
匹配到控制器 = UserController@set
 $arr_param =Array
(
    [0] => Array
        (
            [user_id] => lxn
        )

)
in UserController.set()

v_param
Array
(
    [user_id] => lxn
)
用户id:lxn

http://www.myroute.cn/about

复制代码
$_REQUEST
Array
(
    [real_url] => /about
)

$real_url=about
arr_url=Array
(
    [0] => about
)

==========================================
路由表
Array
(
    [about] => AboutController@index
    [user/get/{username}] => UserController@get
    [user/set/{user_id}] => UserController@set
    [user/del/{user_id}] => UserController@del
    [user/add] => UserController@add
)

==========================================
匹配到路径 = about
匹配到控制器 = AboutController@index
 $arr_param =Array
(
)
这是关于页面

http://www.myroute.cn/index.php?real_url=user/add/mmm

add接口未实现,报错:

复制代码
$_REQUEST
Array
(
    [real_url] => user/add/mmm
)

$real_url=user/add/mmm
arr_url=Array
(
    [0] => user
    [1] => add
    [2] => mmm
)

==========================================
路由表
Array
(
    [about] => AboutController@index
    [user/get/{username}] => UserController@get
    [user/set/{user_id}] => UserController@set
    [user/del/{user_id}] => UserController@del
    [user/add] => UserController@add
)

==========================================
匹配到路径 = user/add
匹配到控制器 = UserController@add
 $arr_param =Array
(
)


Warning:  call_user_func_array() expects parameter 1 to be a valid callback, class 'UserController' does not have a method 'add' in D:\php_projects\myroute\index.php on line 125
相关推荐
BingoGo1 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php
JaguarJack1 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php·服务端
BingoGo2 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php
JaguarJack2 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php·服务端
JaguarJack3 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
后端·php·服务端
BingoGo3 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
php
JaguarJack4 天前
告别 Laravel 缓慢的 Blade!Livewire Blaze 来了,为你的 Laravel 性能提速
后端·php·laravel
郑州光合科技余经理5 天前
代码展示:PHP搭建海外版外卖系统源码解析
java·开发语言·前端·后端·系统架构·uni-app·php
QQ5110082855 天前
python+springboot+django/flask的校园资料分享系统
spring boot·python·django·flask·node.js·php
WeiXin_DZbishe5 天前
基于django在线音乐数据采集的设计与实现-计算机毕设 附源码 22647
javascript·spring boot·mysql·django·node.js·php·html5