codeigniter 2 到 4 不是升级而是重写,因底层彻底重构:类加载改用 psr-4、路由引擎更换、依赖注入引入服务容器、数据库结果封装为 queryresult、配置转为类属性,所有 $this->load->* 调用均失效,需重写模型、库、路由及配置。

CodeIgniter 2 到 CodeIgniter 4 不是升级,是重写。框架底层彻底重构,类加载、路由、依赖注入、数据库层、错误处理全部换血——直接跑 php upgrade.php 或手动替换核心文件只会报错堆满屏幕。
CI2 的 $this->load->library() 在 CI4 里根本不存在
CI2 用全局加载器动态引入类,CI4 改为 PSR-4 自动加载 + 服务容器管理实例。
- $this->load->library('session') → 改用 session() 辅助函数,或注入 SessionInterface
- $this->load->model('user_model') → 模型必须继承 CodeIgniter\Model,且通过 new UserModel() 或依赖注入获取
- 所有自定义库需重写为类,放在 app/Libraries/,并注册到 app/Config/Services.php 中的 public static function mylib() 方法
常见错误现象:
- 报错
Call to undefined method CI_Loader::library() - 模型调用
$this->user_model->get()失败,提示方法不存在(CI4 模型默认不自动加载,且查询方法需显式定义或启用$allowedFields)
CI4 的路由不认 routes.php 里的正则匹配写法
CI2 路由支持类似 $route['product/(:any)'] = 'catalog/product_lookup/$1'; 的伪变量,CI4 路由引擎改用基于 HTTP 方法的闭包或控制器映射,且路径参数必须显式声明。
- 原写法 $route['admin/(:num)'] = 'admin/index/$1'; → 改为 $routes->add('admin/(:segment)', 'Admin::index/$1');(注意::segment 替代 :num,CI4 不再内置数字约束)
- 更推荐写成命名参数:$routes->add('admin/(:id)', 'Admin::index/$1');,并在控制器方法签名中接收 public function index(string $id)
- 若用闭包路由,务必注意返回值:必须返回 ResponseInterface 实例,不能直接 echo 或 return view()(CI4 的 view() 返回字符串,需包装成响应对象)
$db->query() 返回结果在 CI4 里不是数组而是 QueryResult
CI2 的 $this->db->query() 直接返回含 result_array() 方法的对象,CI4 的查询结果封装为 CodeIgniter\Database\Result,方法名和行为有变:
- $query->result_array() 仍可用,但 $query->getResultArray() 是更明确的写法
- $query->row() → $query->getRow();$query->row_array() → $query->getRowArray()
- 如果之前用 foreach ($query as $row) 遍历,CI4 中需先调用 $query->getResult() 或 $query->getResultArray()
- 注意事务控制:CI2 的 $this->db->trans_begin() 在 CI4 中已废弃,改用 $db->transStart() + $db->transComplete(),且失败时不自动回滚,需检查 $db->transStatus()配置文件从 PHP 数组变成类属性,config/autoload.php 彻底消失
CI2 的 config/autoload.php 控制哪些库/辅助函数默认加载,CI4 全部移入 app/Config/Autoload.php 类的属性中:
- $autoload['libraries'] = ['database', 'session']; → 改为 public $libraries = ['database', 'session'];
- $autoload['helper'] = ['url', 'form']; → 改为 public $helpers = ['url', 'form'];
- 自定义配置文件不再放 application/config/,而统一置于 app/Config/ 下,且必须继承 BaseConfig,如 class MyConfig extends BaseConfig
- 环境变量优先级变了:CI4 默认读取 .env,而非 index.php 中的 define(),旧项目若依赖 ENVIRONMENT 常量,需在 public/index.php 里手动设置 $_ENV['CI_ENVIRONMENT']CI4 的迁移陷阱不在语法细节,而在“隐性契约”——比如模型是否启用软删除、时间戳字段是否真实存在、$allowedFields 是否漏配、服务容器是否提前注册。这些不会立刻报错,但会在某次更新后突然丢数据或跳过验证。动手前先跑一遍 php spark serve 并逐个访问路由,比通读文档更能暴露问题。











