codeigniter 本身不原生支持 eloquent,但可通过 illuminate/database 手动集成;ci 2/3/4 集成方式、时机和坑点完全不同,ci 4 必须在 pre_system 事件中初始化 capsule,否则类找不到、模型报 class 'app\models\user' not found。

直接说结论:CodeIgniter 本身不原生支持 Eloquent,但可通过 illuminate/database 手动集成;CI 2/3/4 的集成方式、时机和坑点完全不同,不能混用——尤其 CI 4 必须在 pre_system 事件中初始化 Capsule,否则类找不到、模型报 Class 'App\Models\User' not found。
CI 4 中初始化 Eloquent 必须走 Events.php
CI 4 的 autoloader 在 index.php 之前就已生效,硬塞 require vendor/autoload.php 或在 index.php 里 new Capsule 会失败,因为 Model 类尚未注册到 Composer 自动加载器中(App\Models\* 是由 CI 的 Autoloader 管理的)。
正确做法是利用 CI 4 的事件机制,在系统启动早期注入 Eloquent:
- 在
app/Config/Events.php中注册pre_system回调 - 回调内 require
vendor/autoload.php(确保 illuminate 类可用) - new
Capsule,addConnection,setAsGlobal(),bootEloquent() - 额外调用
Capsule::setContainer(\Config\Services::get('session'))可选,避免某些服务容器依赖报错
模型类必须继承 Illuminate\Database\Eloquent\Model,且不能放错命名空间
CI 4 默认把 App\Models\* 映射到 app/Models/ 目录,但 Eloquent 不认 CI 的自动加载规则——它只认 Composer 的 PSR-4 配置或显式 use。所以模型文件开头必须写全:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
protected $table = 'users';
}
常见错误:
- 漏写
use Illuminate\Database\Eloquent\Model,导致报Class 'Model' not found - 把模型放在
application/models/(CI 2/3 路径),CI 4 下该路径完全不扫描 - 命名空间写成
App\或Models\,缺少App\Models\,导致Class 'User' not found
多数据库连接时,$connection 属性名必须和 addConnection() 第二个参数严格一致
比如你这样注册连接:
$capsule->addConnection($config, 'tenant_db');
那对应模型里就得写:
protected $connection = 'tenant_db';
大小写、下划线、拼写差一个字符都不行。CI 4 下还容易踩另一个坑:Capsule 初始化后,若没调用 bootEloquent(),所有模型的 $connection 都会被忽略,默认走 default 连接。
验证是否生效最简单的方法是执行:
dd((new App\Models\User())->getConnectionName());
输出应为 tenant_db,而不是 default。
关联查询 + with() 在 CI 4 中需手动加载关系类,否则报错
CI 4 默认关闭了 PHP 的自动加载反射(ReflectionClass 无法识别未声明的类),而 Eloquent 的 with('posts') 会尝试动态加载 App\Models\Post。如果 Post 模型没被显式 use 或没在当前文件中定义,就会抛出 Class 'App\Models\Post' not found。
解决办法只有两个:
- 在当前模型或控制器中
use App\Models\Post; - 或改用闭包约束:
with(['posts' => function ($q) { $q->select('id', 'title', 'user_id'); }]),前提是posts关系方法已在模型中正确定义
这个限制不是 Eloquent 的问题,而是 CI 4 的 autoloader 和 PSR-4 加载顺序导致的——它不会像 Laravel 那样在运行时兜底扫描整个 app/Models 目录。
最常被忽略的一点:Capsule 初始化代码一旦执行过就不能重复执行,CI 4 的 request 生命周期里如果多个地方(比如不同 Service 或 Helper)都尝试 new Capsule,会导致 RuntimeException: A facade root has not been set. ——务必加 if (!class_exists('Illuminate\Database\Capsule\Manager')) 或用单例封装。











