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

自定义MVC框架路由参数配置问题:访问domain.com/users/username时出现404错误

自定义MVC框架路由参数配置问题:访问domain.com/users/username时出现404错误

看起来你在自己搭建MVC框架的时候踩了几个典型的路由匹配坑,我帮你梳理下代码里的关键问题,一步步解决这个404和后续可能的视图报错:

1. 路由匹配逻辑的核心问题

你的Router类当前的direct方法是直接用array_key_exists($uri, $this->routes[$requestType])来判断路由是否存在,但带参数的路由(比如users/{username})是动态的,实际请求的URI是users/xxx这种具体值,肯定和路由里的users/{username}键不匹配,所以直接抛出404。

解决办法:修改路由匹配逻辑,支持动态参数解析
更新Router类的direct方法,用正则匹配解析动态参数:

public function direct($uri, $requestType)
{
    foreach ($this->routes[$requestType] as $route => $controller) {
        // 将路由中的{参数}占位符转为正则分组,匹配字母、数字、下划线和短横线
        $pattern = preg_replace('/\{([a-z]+)\}/', '([a-zA-Z0-9-_]+)', $route);
        // 加上首尾锚点,确保完全匹配
        $pattern = "#^$pattern$#i";

        // 匹配当前请求的URI
        if (preg_match($pattern, $uri, $matches)) {
            // 移除第一个匹配的完整URI字符串,剩下的就是提取到的参数
            array_shift($matches);
            // 调用控制器动作并传递参数
            return $this->callAction(
                ...explode('@', $controller),
                $matches
            );
        }
    }

    throw new Exception('Error 404 page not found');
}

2. 控制器方法参数传递问题

原来的callAction方法没有把提取到的参数传递给控制器的动作方法,就算路由匹配成功,show($username)也拿不到参数值,后续还是会报错。

解决办法:更新callAction方法,支持参数传递

protected function callAction($controller, $action, $params = [])
{
    $controller = "App\\Controllers\\{$controller}";
    $controller = new $controller();

    if (method_exists($controller, $action)) {
        // 把提取到的参数展开传递给动作方法
        return $controller->$action(...$params);
    }

    throw new Exception('Error method not found');
}

3. 视图变量不匹配问题

你的UsersController的show方法传递给视图的是$user变量,但show.view.php里用的是$filterUsers,这会导致视图报错;另外如果你的select方法返回的是单条用户数据,也不需要用foreach循环遍历。

解决办法:修正视图变量和渲染逻辑
更新show.view.php:

<?php require 'partials/head.php' ?>

<h1>User Name</h1>
<?php if ($user): ?>
    <p><?php echo $user['name']; ?></p>
<?php else: ?>
    <p>User not found</p>
<?php endif; ?>

<?php require 'partials/footer.php'; ?>

另外建议检查下你的QueryBuilder的select方法返回值:如果它返回的是符合条件的用户数组(哪怕只有一条),需要在控制器里取第一个元素,避免视图报错:

public function show($username)
{
    $user = App::get('database')->select('users', ['name' => $username]);
    // 取第一条结果,没有则设为null
    $user = !empty($user) ? $user[0] : null;
    return view('user', compact('user'));
}

备注:内容来源于stack exchange,提问作者DLK

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 12:35:27