You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP自定义MVC框架实现URL多参数传递与控制器获取

实现带参数的PHP MVC路由匹配与参数传递

1. 路由规则的正则转换

首先要把带{id}、{secondid}这类占位符的路由规则,转换成能匹配真实URL的正则表达式。核心是将占位符替换为正则捕获组,同时保留URL的结构。

比如路由规则/product/{id}/{secondid},需要转换成正则#^/product/([^/]+)/([^/]+)$#:

  • ^和$确保完全匹配整个URL路径,避免部分匹配导致的错误
  • ([^/]+)匹配任意非斜杠字符(作为参数值)
  • #作为正则分隔符,避免和URL中的/冲突

可以写一个辅助函数自动完成转换:

private function convertRouteToRegex(string $route): string
{
    // 把{param}格式的占位符替换为正则捕获组
    $regex = preg_replace('/{([a-zA-Z0-9_]+)}/', '([^/]+)', $route);
    // 添加首尾锚点,确保完全匹配
    return "#^$regex$#";
}

2. 路由匹配与参数提取

在handle方法中,先获取当前请求的URL路径,再遍历所有已注册的路由,用转换后的正则逐个匹配。匹配成功后,提取参数值并关联到对应的占位符名称。

完整的handle方法示例:

public function handle()
{
    // 获取当前请求的URI(剔除查询字符串)
    $uri = trim(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH), '/');
    // 统一URI格式,添加开头斜杠
    $uri = '/' . $uri;

    // 遍历所有已注册路由(假设$this->routes存储路由,格式为['路由规则' => ['控制器', '方法']])
    foreach ($this->routes as $route => $action) {
        $regex = $this->convertRouteToRegex($route);
        if (preg_match($regex, $uri, $matches)) {
            // 移除第一个匹配项(整个URL),剩下的就是参数值
            array_shift($matches);
            
            // 提取路由中的占位符名称
            preg_match_all('/{([a-zA-Z0-9_]+)}/', $route, $paramNames);
            $paramNames = $paramNames[1];
            
            // 将参数值与名称关联成数组(可选,也可直接按顺序传递)
            $params = array_combine($paramNames, $matches);
            
            // 实例化控制器并调用方法
            list($controller, $method) = $action;
            $controllerInstance = new $controller();
            
            // 两种参数传递方式:
            // 方式1:按顺序传值(适合控制器方法参数顺序与路由占位符一致)
            call_user_func_array([$controllerInstance, $method], $matches);
            
            // 方式2:传递关联数组(适合按参数名接收,需调整控制器方法)
            // $controllerInstance->$method($params);
            
            exit; // 匹配到路由后终止后续处理
        }
    }

    // 未匹配到路由时返回404
    http_response_code(404);
    echo "404 Not Found";
}

3. 控制器接收参数

根据选择的传递方式,控制器方法可以这样编写:

方式1:按顺序接收参数

class ProductController
{
    public function show($id, $secondid)
    {
        echo "产品ID:{$id},二级ID:{$secondid}";
    }
}

方式2:接收关联数组参数

class ProductController
{
    public function show($params)
    {
        echo "产品ID:{$params['id']},二级ID:{$params['secondid']}";
    }
}

4. 路由注册示例

确保路由注册格式正确:

$router = new Route();
// 注册带参数的路由
$router->get('/product/{id}/{secondid}', ['ProductController', 'show']);
// 注册基础路由
$router->get('/about-us', ['PageController', 'about']);

额外优化点

  • 参数类型限制:如果需要限制参数为数字(如ID),可以修改正则替换逻辑:
    // 先替换{id}为数字捕获组,再处理其他占位符
    $regex = preg_replace('/{id}/', '(\d+)', $route);
    $regex = preg_replace('/{([a-zA-Z0-9_]+)}/', '([^/]+)', $regex);
    
  • 兼容末尾斜杠:允许URL末尾带或不带斜杠,可修改正则为:
    return "#^$regex/?$#";
    

内容的提问来源于stack exchange,提问作者Praful Rambade

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 03:51:20