CI4 是对 CI3 的彻底重写,非兼容性升级:命名空间、目录结构、类继承、配置方式、数据库操作、路由规则、中间件、缓存会话等全部变更,需重构而非替换。

CI3 升级到 CI4 是破坏性升级,不能直接替换文件
CodeIgniter 4 不是 CodeIgniter 3 的补丁更新,而是完全重写的框架,命名空间、目录结构、核心类继承关系全部变更。试图通过覆盖 system/ 或修改 index.php 来“升级”,结果一定是白屏、类找不到或 Fatal error: Class 'CI_Controller' not found。
- CI3 的
application/目录在 CI4 中变为app/,且内部结构(如controllers/→Controllers/)需按 PSR-4 规范调整大小写 - 所有控制器必须改用
namespace App\Controllers;,并继承BaseController,而非CI_Controller -
config/目录整体移入app/Config/,且配置类名全变(如Config.php→App.php),旧配置文件直接复制过去会报错 - CI4 默认使用 Composer 自动加载,手动 require 或 $autoload 数组已失效
数据库迁移和模型层必须重写,不能沿用 CI3 查询逻辑
CI4 的查询构建器虽保留了 where()、get() 等方法名,但返回值类型、链式调用行为、错误处理机制完全不同;更关键的是,模型不再只是查询封装器,而是需显式定义实体(Entity)与仓储(Repository)边界。
-
$this->db->query()返回的是CodeIgniter\Database\Result对象,不是数组,需显式调用getResult()或getRow() - CI3 中常见的
$this->model->where(...)->get()->row()在 CI4 中应改为$this->model->where(...)->first()(前提是模型继承Model并配置了表名) - 若用了 CI3 的自定义查询类或 Active Record 扩展,全部失效;CI4 不再支持
$this->db->from()+$this->db->join()混合链式写法,必须统一用builder实例或模型方法 - 事务控制从
$this->db->trans_start()改为$this->db->transBegin(),且需手动commit()/rollback()
路由和中间件配置必须重建,routes.php 格式彻底不同
CI3 的 routes.php 是简单键值映射($route['default_controller'] = 'welcome';),而 CI4 的 app/Config/Routes.php 是一个 PHP 类方法调用集合,支持分组、命名、中间件绑定和 REST 资源路由 —— 没有平滑过渡语法。
- CI3 中的
$route['admin/(:any)'] = 'admin/$1';在 CI4 中要写成$routes->add('admin/(:segment)', 'Admin::$1'); - 所有带参数的路由必须显式声明占位符类型:
(:num)、(:alpha)、(:segment),否则匹配失败 - 中间件(如权限校验)不能靠控制器构造函数里写逻辑,必须注册到
app/Config/Services.php并在路由中用$routes->add(..., ..., ['middleware' => 'auth']); - 如果你用了 CI3 的 HMVC 或第三方路由扩展,全部不兼容;CI4 原生不支持模块化目录结构,需靠命名空间 + 自定义服务注入模拟
缓存、会话、日志等系统配置项位置和默认值全变了
CI4 把运行时行为拆得更细,很多看似“小配置”的变动会导致功能静默失效,比如缓存不生效、会话无法跨请求保持、日志写不进文件 —— 表面没报错,实际逻辑断了。
- 缓存驱动配置从
application/config/cache.php移至app/Config/Cache.php,且$handler必须设为'file'、'redis'等字符串,不能留空或设为false - 会话配置中的
$config['sess_save_path']在 CI4 中变成public $storePath = WRITEPATH . 'session';,路径必须可写,且不能复用 CI3 的 session 表结构 - 日志等级由
app/Config/Logger.php控制,默认只记录 ERROR 级别,DEBUG 日志需手动开启public $threshold = 4; - CSRF 保护默认启用,但 token 字段名从
csrf_test_name变为csrf_token_name,表单里忘了改就会一直提示“Token Mismatch”










