CodeIgniter 4 中配置404重定向须在app/Config/Routes.php中调用$routes->set404Override('Errors::show404'),对应控制器需位于app/Controllers/Errors.php且继承BaseController,视图须复制至app/Views/errors/html/error_404.php并加载url辅助函数。

设置 $route['404_override'] 必须在 app/Config/Routes.php 中
CodeIgniter 4 不再使用 application/config/routes.php,所有路由配置统一放在 app/Config/Routes.php。如果你在旧路径下修改,CI4 完全不会读取——这是最常被忽略的起点错误。
打开 app/Config/Routes.php,在文件末尾(或 services() 之后、if (ENVIRONMENT !== 'production') 块之外)添加:
$routes->set404Override('Errors::show404');
注意:set404Override() 接收的是「类名::方法名」字符串,且类必须带命名空间(默认是 App\Controllers),所以实际等价于调用 App\Controllers\Errors::show404()。
- 不能写成
'errors/show404'(CI3 风格,CI4 不识别) - 不能漏掉
::,写成'Errors:show404'会报错Call to undefined method - 类名首字母必须大写,
errors或ErrorsController都不合法
控制器类 Errors 必须存在且继承 BaseController
CI4 的 404 处理器不是普通控制器,它必须能被框架无条件加载——这意味着它不能依赖中间件、不能 require 登录态、不能有构造函数里抛异常的逻辑。
创建 app/Controllers/Errors.php,内容至少包含:
<?php
namespace App\Controllers;
use CodeIgniter\Controller;
class Errors extends BaseController
{
public function show404()
{
// 可选:设置 404 状态码(CI4 默认已设,但显式写更稳妥)
$this->response->setStatusCode(404);
// 加载视图(推荐用 view(),不要 echo 或 print_r)
return view('errors/html/error_404');
}
}
- 必须声明
namespace App\Controllers,否则set404Override()找不到类 - 不能用
extends Controller(CI4 中已弃用,应继承BaseController) - 方法名必须和
set404Override()中指定的一致,大小写敏感 - 不要在
show404()里调用redirect()——这会变成 302 跳转,HTTP 状态码不再是 404,SEO 和调试都会混乱
视图路径必须是 app/Views/errors/html/error_404.php
CI4 内置了标准 404 视图模板,位于 system/Views/errors/html/error_404.php。但直接使用它会导致 URL 辅助函数(如 base_url())不可用,报 Call to undefined function base_url() ——因为 404 视图渲染时,辅助函数未自动加载。
正确做法是复制一份到应用目录,并确保加载必要辅助函数:
- 复制
system/Views/errors/html/error_404.php到app/Views/errors/html/error_404.php - 在
app/Config/View.php的$helpers数组中加入'url':public $helpers = ['html', 'url'];
- 或者在
Errors::show404()方法开头手动加载:helper('url');
否则你在视图里写 <link href="= base_url('css/app.css') ?>"> 就会直接崩溃。
测试时别用浏览器缓存或重定向历史干扰判断
CI4 的 404 路由只在「完全匹配失败」时触发。如果某个 URL 实际命中了某条路由规则(哪怕目标控制器不存在),那走的是「控制器加载失败」流程,不是 set404Override()。
验证是否生效的干净方式:
- 访问一个明显不存在的路径,例如
/nonexistent/route/123 - 确保该路径没被任何其他
$routes->get()或通配符规则捕获 - 禁用浏览器缓存(DevTools → Network → Disable cache),避免看到上次 302 跳转的缓存响应
- 检查响应头中的
Status: 404,而不是只看页面内容
真正容易被忽略的是:CI4 的 set404Override() 仅接管「路由匹配失败」,不接管「控制器存在但方法不存在」或「控制器类文件损坏」这类错误——那些仍会抛出 PHP 异常或显示白屏。


















