最常见原因是新字段未加入验证白名单或schema缓存未刷新:检查rules()是否含'safe'、scenarios()是否显式包含该字段;清空schema缓存(php yii cache/flush-schema);确认updateall()使用数据库列名而非属性名,并检查opcache是否生效。

模型赋值后调用 save() 却不更新字段,最常见原因是新字段没进验证白名单,或 Schema 缓存没刷新。
字段被 attributes 批量赋值时被过滤掉
当你写 $model->attributes = $data;,Yii 会按当前 scenario 和 rules() 中声明的 safe 字段来过滤 $data —— 不在白名单里的字段直接丢弃,连日志都不会报。
- 检查模型类的
rules()方法,确认新加字段是否加了'safe'或对应验证规则(如['new_field', 'string']) - 若用的是
default场景,scenarios()里必须显式包含该字段,否则attributes赋值时自动跳过 - 临时验证:改成
$model->setAttributes($data, false)(第二个参数false表示跳过安全过滤),再save()看是否生效 —— 如果这时能更新,就坐实是白名单问题
数据库字段存在但模型不知道(Schema 缓存滞后)
加完数据库字段、跑完 migration 后,模型仍报 Unknown property 或静默忽略该字段,基本是 Schema 缓存没清。
- 开发阶段快速验证:在 action 里加一行
Yii::$app->cache->flush();,然后刷新页面(⚠️ 生产环境严禁保留) - 规范做法:migration 执行完立刻运行
php yii cache/flush-schema,它只清 ActiveRecord 的表结构缓存,不影响其他数据 - 如果用了 Redis 做缓存,且
cache组件指向 Redis,也可手动执行redis-cli -n <db> FLUSHDB</db>(注意选对 DB 编号)
用 updateAll() 时字段名写错或条件失效
想绕过模型直接批量更新?updateAll() 不走验证、不触发钩子,但字段名和条件稍有偏差就会“看似成功实则零更新”。
- 确认传入的字段数组键名是数据库列名,不是模型属性别名(例如数据库是
opnop_visible,别写成is_visible) - 检查
$condition是否真能匹配到记录:先用SELECT COUNT(*) FROM xxx WHERE ...手动验证条件逻辑 - 留意
updateAll()返回的是影响行数(int),不是布尔值 —— 返回0就代表没更新任何记录,得回头查条件或数据是否存在
真正容易被忽略的是:字段加进数据库、migration 也跑了、rules() 看似加了,但模型类文件被 opcache 缓存住了,改完代码根本没重载。部署后务必确认 opcache.revalidate_freq = 0(开发)或 systemctl reload php*-fpm(生产),否则你改的每一行都可能白改。











