yii2中activerecord新增数据最简路径是调用save(),需确保模型绑定表、属性赋值且验证通过;常见错误包括save()返回false未查geterrors()、safe规则丢弃字段、自增主键误赋值。

Yii2 中使用 ActiveRecord 新增数据最简路径
直接调用 save() 是新增数据的默认方式,但必须确保模型已正确绑定表、属性已赋值、且验证通过。不手动写 SQL、不拼接字符串,这是 Yii 的核心优势。
常见错误现象:save() 返回 false 却没查 getErrors();字段被 safe 规则拦截导致静默丢弃;主键为自增却手动赋了空字符串或 0。
- 模型类需继承
yii\db\ActiveRecord,且必须定义tableName()静态方法 - 新增前务必调用
load()或逐个赋值,再调用validate()检查(save()内部会自动触发,但调试时显式调用更可控) - 若表主键非自增(如 UUID),需在保存前手动设置
$model->id = \yii\helpers\Uuid::uuid4()->toString(); - 批量插入不用
save(),改用yii\db\Command::batchInsert(),否则性能断崖下跌
为什么 save() 有时不报错却没插入成功
根本原因通常是验证失败或事务被回滚,而代码里没处理返回值。Yii 不抛异常,而是静默返回 false。
典型场景:数据库字段设了 NOT NULL,但模型规则里漏写了 required;或设置了 default 值但数据库层面没设默认,导致 PHP 层传 null 被拒绝。
- 永远检查
if (!$model->save()) { var_dump($model->getErrors()); } - 注意时间字段:若数据库是
DATETIME类型,PHP 层传'now'字符串会被忽略,应传date('Y-m-d H:i:s')或用time() - 关联字段(如外键)未通过
scenarios()开放,即使数据库允许NULL,也会因验证失败被拦住
带事务的新增操作怎么写才安全
单条记录新增一般不需要手动开事务,但涉及多模型联动(如用户注册同时写 profile 表)就必须包裹 beginTransaction(),否则部分失败会导致数据不一致。
$transaction = \Yii::$app->db->beginTransaction();
try {
$user = new User();
$user->username = 'alice';
$user->email = 'a@b.c';
if (!$user->save()) throw new \Exception('User save failed');
$profile = new Profile();
$profile->user_id = $user->id;
$profile->bio = 'Hello world';
if (!$profile->save()) throw new \Exception('Profile save failed');
$transaction->commit();
} catch (\Exception $e) {
$transaction->rollBack();
throw $e;
}
- 不要在事务里调用
Yii::$app->db->createCommand()->insert()混用原生 SQL,除非你确认它共享同一连接和事务上下文 - 事务中避免调用外部 HTTP 请求或文件写入,超时或失败会导致事务长期挂起
- Yii2 默认事务隔离级别是
READ COMMITTED,高并发下注意幻读问题,必要时手动SELECT ... FOR UPDATE
新增后怎么拿到刚插入的 ID 或其他字段
save() 成功后,主键字段(通常是 id)会自动同步更新,无需再查一次数据库。但要注意:仅限主键由数据库自动生成(如 AUTO_INCREMENT)且模型正确配置了 primaryKey()。
- 直接访问
$model->id即可,前提是该字段在模型中声明为public $id;或通过attributes()可读 - 若主键不是
id(比如叫user_uuid),需在模型中重写primaryKey()方法返回['user_uuid'] - 新增后想立刻获取数据库生成的默认值(如 MySQL 的
CURRENT_TIMESTAMP),得在afterSave()里重新$this->refresh(),否则字段仍是 null
NULL,但模型规则强制 required,结果前端没传值就卡死;或者反过来,模型没设规则,但数据库限制了长度,插入时直接报 SQLSTATE[22001] 截断错误。这两边得对齐,不能只信一边。











