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

如何为PHP路由传递参数?现有路由代码适配求助

实现带参数的PHP自定义路由系统

你的现有路由系统仅支持精确路径匹配,无法处理带动态参数的路由。以下是修改方案,让路由支持{param}格式的动态参数,并能在回调/控制器中直接获取参数值。

修改Router核心类

替换原resolve方法,添加路由参数匹配和参数传递逻辑:

<?php
namespace app\core;
class Router{
    public Request $request;
    public Response $response;
    protected array $routes = [];

    public function __construct(Request $request, Response $response)
    {
        $this->request = $request;
        $this->response = $response;
    }

    public function get($path, $callback){
        $this->routes['get'][$path] = $callback;
    }

    public function post($path, $callback){
        $this->routes['post'][$path] = $callback;
    }

    public function resolve(){
        $path = $this->request->getPath();
        $method = $this->request->getMethod();
        $callback = false;
        $params = [];

        // 遍历当前请求方法的所有路由,匹配带参数的路径
        foreach ($this->routes[$method] ?? [] as $routePath => $routeCallback) {
            // 将路由中的 {param} 转换为正则捕获组(匹配除/外的任意字符)
            $pattern = preg_replace('/\{([a-zA-Z0-9_]+)\}/', '([^/]+)', $routePath);
            // 添加正则锚点,确保路径完全匹配
            $pattern = '#^' . $pattern . '$#';

            if (preg_match($pattern, $path, $matches)) {
                $callback = $routeCallback;
                // 移除第一个匹配项(整个路径字符串)
                array_shift($matches);
                // 提取路由中定义的参数名
                preg_match_all('/\{([a-zA-Z0-9_]+)\}/', $routePath, $paramNames);
                $paramNames = $paramNames[1];
                // 关联参数名和对应的值
                foreach ($paramNames as $index => $name) {
                    $params[$name] = $matches[$index] ?? null;
                }
                break;
            }
        }

        if (!$callback) {
            $this->response->setStatusCode(404);
            return "Not Found";
        }

        // 处理控制器类方法的情况:实例化控制器并传递参数
        if (is_array($callback)) {
            $controller = new $callback[0]();
            return call_user_func_array([$controller, $callback[1]], $params);
        }

        // 处理闭包或全局函数的情况:直接传递参数
        return call_user_func_array($callback, $params);
    }
}

使用带参数的路由

闭包回调示例

注册带参数的路由后,闭包可以直接接收参数:

$app->router->get('/contact/{id}', function($id){
    echo "Contact ID: " . $id;
});

控制器方法示例

先在控制器中定义接收参数的方法:

<?php
namespace app\controllers;

class Home {
    public function showContact($id) {
        echo "Controller: Contact ID is " . $id;
    }
}

然后注册路由:

$app->router->get('/contact/{id}', [Home::class, 'showContact']);

多参数路由支持

也可以定义多个动态参数,参数会按顺序传递给回调/方法:

$app->router->get('/user/{userId}/post/{postId}', function($userId, $postId){
    echo "User ID: $userId, Post ID: $postId";
});

优化思路

  • 参数类型限制:可以扩展路由语法,比如{id:int}限制参数为数字,修改正则替换规则为preg_replace('/\{([a-zA-Z0-9_]+):int\}/', '(\d+)', $routePath)
  • 路由缓存:提前将所有路由转换为正则表达式并存入缓存,避免每次请求重复执行正则转换逻辑
  • 参数注入Request:将提取到的参数存入Request对象(新增setParams和getParam方法),这样可以在任意地方通过$request->getParam('id')获取参数,适配更复杂的场景
  • 可选参数:支持{param?}格式的可选参数,对应的正则改为([^/]*),并处理参数为null的情况

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 12:01:20