ci3升级到ci4是重写而非升级:底层架构、命名空间、目录结构、路由语法、数据库操作、自动加载机制全部变更,必须重构代码,直接替换文件或复制目录会导致白屏或class 'ci_controller' not found错误。

CI3 升级到 CI4 不是升级,是重写——直接替换文件、改 index.php 或复制 application/ 目录过去,99% 会白屏或报 Fatal error: Class 'CI_Controller' not found。
为什么 composer update codeigniter4/framework 会失败
CI4 的自动加载依赖 PSR-4 和命名空间,而 CI3 的 $autoload 数组、require_once 手动引入、甚至 system/core/Controller.php 这类路径在 CI4 中根本不存在。运行 composer update 时 Composer 会尝试解析旧类名(如 CI_Controller),但找不到对应命名空间,直接中断或抛出解析错误。
- CI4 的核心控制器是
CodeIgniter\Controller\BaseController,必须用namespace App\Controllers;+extends BaseController -
app/Config/Database.php是类,不是数组;$default是静态属性,不能照搬 CI3 的$db['default']数组写法 - CI3 的
config/autoload.php在 CI4 中完全失效,所有类都走 Composer 自动加载
routes.php 迁移到 Routes.php 的硬性规则
CI4 的路由注册不是键值映射,而是调用 $routes 实例方法,且 HTTP 方法(get/post)必须显式声明,否则 404。
- CI3 写法:
$route['admin'] = 'admin/dashboard';→ CI4 必须写成$routes->get('admin', 'Admin::dashboard'); - 带参数路由必须标注类型:
$route['user/(:num)']→$routes->get('user/(:num)', 'User::profile/$1');,不写(:num)就匹配不到 -
(:any)在 CI4 中已被移除,等效的是(:segment)(不含/)或(.*)(含斜杠,需谨慎) - 闭包路由虽可用,但
spark routes命令无法识别,调试时容易遗漏
模型和数据库查询最容易出静默错误
CI4 的 Model 类不自动加载,$this->db->query() 返回的是 CodeIgniter\Database\Result 对象,不是数组;很多“看起来有结果”的查询,实际是空对象或未调用取值方法。
-
$this->db->table('users')->select('id,name')->get()必须接getResult()(返回对象数组)或getRow()(单行对象),否则没数据 - CI3 的
$model->where()->get()->row()→ CI4 应改用$model->where('id', $id)->first(),前提是模型已配置protected $table = 'users'; - 事务控制从
$this->db->trans_start()改为$this->db->transBegin(),且必须配对transCommit()或transRollback() - 自定义查询类、
$this->db->from() + $this->db->join()混合链式写法全部失效,必须用 builder 实例或模型内置方法
最常被忽略的点:CI4 默认开启 DBDebug,但只在开发环境生效;生产环境里 DSN 错误或驱动未启用(比如没开 mysqli 扩展),会静默返回空数组而不是报错——查不到数据时先看 PHP 错误日志,再确认 app/Config/Database.php 的 DBDriver 和扩展是否就位。











