codeigniter 4 模型必须在类中用 protected $table = '表名' 显式声明表名,不可动态赋值或使用变量/常量;该值区分大小写、含前缀,且仅影响主表,join 表名需手动指定。

Model 类中设置 $table 属性是唯一可靠方式
CodeIgniter 4 的模型必须显式声明操作的表名,没有自动推导机制。不设 $table,调用 find()、update() 等方法会直接报错:Call to a member function from() on null 或提示“no table specified”。
正确做法是在模型类中定义 $table 成员变量:
namespace App\Models;
use CodeIgniter\Model;
class UserModel extends Model
{
protected $table = 'users'; // 必须写,且为字符串字面量
}
-
$table必须是字符串,不能是变量、常量或表达式(如self::TABLE_NAME或env('USER_TABLE')) - 表名区分大小写,需与数据库实际名称完全一致(尤其在 Linux 环境下)
- 若使用前缀(如
ci4_),应包含在$table值里,例如'ci4_users';CI4 不会自动拼接前缀
CI4 中 $table 和 CI3 的 $this->table 写法完全不同
CI3 允许在构造函数里动态赋值:$this->table = 'users';,但 CI4 的模型属性是静态绑定的,构造函数中修改 $this->table 无效——因为底层查询构建器在实例化时就已读取该属性。
以下写法在 CI4 中不起作用:
public function __construct()
{
parent::__construct();
$this->table = 'users'; // ❌ 无效!不会被识别
}
- CI4 模型所有关键配置(
$table、$primaryKey、$allowedFields)都必须用protected声明并直接赋值 - 试图通过构造函数覆盖会导致查询失败,且无明确错误提示,容易卡在空结果或 500 错误上
- 如果表名需运行时切换(极少见),应新建不同模型类,而非复用同一类改
$table
关联查询时 $table 不影响 join() 表名
模型的 $table 只决定主表(即 FROM 子句),join() 所用表名完全独立,需手动传入完整表名字符串:
$users = $this->select('users.name, profiles.bio')
->join('profiles', 'profiles.user_id = users.id')
->findAll();
- 上面例子中,
$this是UserModel,其$table = 'users'自动用于FROM users,但join()的'profiles'必须显式写出 - 不能写成
->join($this->table, ...)来复用主表名,因为join()需要的是被连接表,不是主表 - 若连接表也对应一个模型,建议单独加载该模型做查询,而不是硬编码表名,便于后期迁移或测试
软删除启用后 $table 仍指向原表,不自动切到视图或影子表
启用软删除($useSoftDeletes = true)不会改变 $table 含义,它只是让所有 delete() 变成 UPDATE,并在 SELECT 自动加 WHERE deleted_at IS NULL。表本身仍是原物理表。
-
$table = 'users'就永远查users表,哪怕你建了users_archive视图也不自动切换 - 若真需查归档数据,应新建一个模型(如
UserArchiveModel),单独设$table = 'users_archive' - 不要试图在同一个模型里通过条件切换
$table值——模型类设计就是单表绑定,强行多表会破坏缓存、验证和事件机制
$this->table 就生效了,其实框架压根没读它。











