CodeIgniter 2/3 升级到 4 是重写而非升级:底层架构、命名空间、目录结构、路由语法、数据库操作、会话与库加载机制全部变更,必须重构代码而非简单配置调整。

CodeIgniter 大版本升级(比如 2→4 或 3→4)不是升级,是重写——CI_Controller 找不到、$this->load->view() 报错、路由白屏,这些不是配置没改对,而是框架底层已完全换血。
为什么 composer update codeigniter/framework 会失败
CI4 不是 CI3 的补丁包,它没有 system/core/Controller.php,也不读 application/config/routes.php。直接运行 composer update 会卡在命名空间解析失败,或抛出 Fatal error: Class 'CI_Controller' not found。CI4 的 BaseController 在 CodeIgniter\Controller 命名空间下,且默认启用 PSR-4 自动加载。
- CI2/CI3 的
application/目录在 CI4 中对应app/,但子目录名必须首字母大写:controllers/→Controllers/ -
config/整体迁入app/Config/,旧文件如config/database.php不能直接复制,需重写为app/Config/Database.php类,其中$default是静态属性,不是数组键 - CI4 默认启用
strictOn模式,MySQL 连接若用旧版mysql_*驱动(PHP 7.0+ 已移除)会直接拒绝启动
routes.php 怎么迁移到 Routes.php
CI4 的路由注册方式从全局数组变为 $routes 实例方法调用,且不支持 $route['news/(:any)'] 这类字符串映射语法。旧路由规则若未重写,请求将 404 或进入默认控制器。
- CI3 路由
$route['admin'] = 'admin/dashboard';→ CI4 写成$routes->get('admin', 'Admin::dashboard'); - 带参数的路由必须显式声明:CI3 的
$route['user/(:num)'] = 'user/profile/$1';→ CI4 改为$routes->get('user/(:num)', 'User::profile/$1');,注意get/post必须匹配 HTTP 方法 - 闭包路由在 CI4 中可用但不推荐,因无法被 CLI 命令(如
spark routes)识别,调试时容易遗漏
模型和数据库操作差异最易引发静默错误
CI4 的 Model 类不再自动加载,也不再提供 $this->db->query() 的全局快捷方式。很多“看起来跑通”的查询,实际走的是缓存或空结果集,尤其在分页、事务、字段别名场景下表现异常。
- CI3 中
$this->db->select('id, name')->from('users')->get()→ CI4 必须用$builder = $this->db->table('users'); $builder->select('id, name'); $builder->get();,或继承CodeIgniter\Model后调用$this->findAll() - CI4 默认开启
DBDebug,但仅在开发环境生效;生产环境若未配置database.default.DBDriver或 DSN 格式错误,会静默返回空数组而非报错 - CI3 的
$this->db->escape()在 CI4 中已废弃,应改用查询构造器或预处理语句:$builder->where('status', $status)->get();
Session 和库加载必须显式声明
CI2/CI3 中 $this->load->library('session') 是隐式初始化,CI4 要求显式获取服务实例,否则 $this->session 属性为空,且不会触发任何警告。
- 控制器中使用 Session:需在
__construct()中调用$this->session = \Config\Services::session();,或更推荐在app/Controllers/BaseController.php的构造函数里统一注入 - 自定义库(如
application/libraries/MY_Email.php)不能直接复制进app/Libraries/,必须添加命名空间namespace App\Libraries;并继承对应基类(如CodeIgniter\Email\Email) -
hooks.php在 CI4 中已被中间件(Middleware)替代,旧钩子逻辑需重写为app/Middleware/下的类,并在app/Config/Filters.php中注册
真正麻烦的不是改代码,而是那些没报错却逻辑偏移的地方:比如 CI3 中 $this->input->post() 对空值返回 null,而 CI4 的 $this->request->getPost() 默认返回空字符串;又比如分页类的 uri_segment 参数位置变化,导致第一页永远显示第二页数据——这类问题只在真实用户点击后才暴露,必须用端到端流程覆盖验证,不能只靠单元测试扫过。


















