codeigniter 4需显式注册路由:/home和/根路径须用$routes->get()绑定home::index;动态参数用(:num)或正则捕获;crud场景可用resource()批量生成;语义化链接需通配符+控制器查库兜底并抛出pagenotfoundexception。

让 /home 正常访问 Home 控制器的 index 方法
你在浏览器输入 http://localhost/home 却看到 404 - Can't find a route for 'get: home',说明 CodeIgniter 4 并未自动把 URL 路径映射到同名控制器——这和 CI3 完全不同,CI4 默认关闭自动路由,所有路径必须显式注册。
打开 app/Config/Routes.php 文件,在 $routes->set404Override() 之前、静态路由区块中插入这一行:
$routes->get('/home', 'Home::index');
注意:路径必须以 / 开头,控制器名 Home 首字母大写,方法名 index 小写,双冒号不可写成单冒号或点号;文件 app/Controllers/Home.php 必须存在且类定义为 class Home extends BaseController。
保存后刷新页面,/home 即可正常加载。若仍报错,请先执行 php spark cache:clear 清除路由缓存——CI4 缓存生效后不会自动重读 Routes.php。
配置根路径 / 指向首页控制器
用户访问域名根目录(如 http://localhost/)时,默认应展示欢迎页或主页内容,这需要单独设置默认路由。
在 Routes.php 同一区块内,添加:
$routes->get('/', 'Home::index');
这行代码优先级高于通配符路由,且不依赖任何 URL 参数。它和 $route['default_controller'] = 'home';(CI3 写法)完全无关——CI4 中该配置项已废弃,必须用 $routes->get() 显式声明。
如果你删掉了这行,又没配置其他 / 路由,访问根路径就会直接触发 404。
支持动态参数的路由写法
当需要匹配类似 /product/123 或 /user/john 这类带变量的 URL 时,不能硬编码路径,得用占位符捕获值并传入控制器。
方法一:使用内置占位符
$routes->get('/product/(:num)', 'Product::view/$1');
其中 (:num) 只匹配纯数字,$1 表示将捕获到的数字作为第一个参数传给 Product::view() 方法。控制器中接收参数必须写成 public function view(int $id),类型提示不能省略,否则会因类型不匹配抛出错误。
方法二:用正则表达式控制更严苛的格式
$routes->get('/user/([a-zA-Z][a-zA-Z0-9_]{2,19})', 'User::profile/$1');
这条规则只允许用户名以字母开头、含 3–20 个字母数字下划线,避免无效 slug 触发数据库查询。注意正则括号必须是英文半角,且需用 $1 引用——写成 $2 或漏掉 $ 符号都会导致参数丢失。
批量注册资源型路由(适合 CRUD 场景)
当你有一组标准增删改查操作时,手动写七八条路由既重复又易错,CI4 提供了 resource() 方法一键生成完整 RESTful 路由表。
第一步:在 Routes.php 中调用
$routes->resource('posts');
第二步:确认控制器命名规范
必须存在 app/Controllers/Posts.php,类名为 Posts(复数、首字母大写),且继承 BaseController;方法名严格对应:index、show、new、create、edit、update、remove、delete。
第三步:验证生成结果
运行 php spark routes 命令,你会看到自动列出 8 条路由,例如 GET /posts Posts::index 和 DELETE /posts/(:num) Posts::delete/$1。这些路由全部启用,无需额外配置。
第四步:按需排除不需要的方法
如果不需要删除功能,改成 $routes->resource('posts', ['except' => ['delete', 'remove']]); 即可剔除对应路由,避免误暴露危险接口。
绕过静态路由限制:实现数据库驱动的语义化链接
博客文章 URL 不该是 /post/123,而应是 /how-to-configure-ci4-routes——这种 slug 存在数据库里,无法预先写死所有路由,必须靠通配符 + 控制器层兜底查询。
方法一:高优先级通配符捕获
在 Routes.php 中,将这条规则放在所有具体路由之后、$routes->set404Override() 之前:
$routes->get('(:any)', 'BlogController::show/$1');
⚠️ 注意:(:any) 会匹配任意非空字符串(不含斜杠),所以它绝不能放在最前面,否则 /admin、/login 全部被劫持到 BlogController,后台就进不去了。
方法二:控制器中查库并精准响应
在 app/Controllers/BlogController.php 的 show() 方法里,用 slug 查询模型:
$post = (new PostModel())->where('slug', $slug)->first();
如果 $post 为空,必须主动抛出 \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound(),否则用户会看到空白页或 PHP 错误,而不是预期的 404 页面。










