要使时间戳字段可为空,需同时满足:数据库字段设为 NULL、模型 rules() 中声明可为空、TimestampBehavior 的 value 回调返回 null;并禁用 loadDefaultValues 和数据库默认值。

数据库字段设为允许 NULL,模型规则里声明该字段可为空,再配合 TimestampBehavior 的 value 回调做空值判断,三者缺一不可。
数据库层面:字段要支持 NULL
建表或修改字段时,确保时间戳字段允许为空。例如 MySQL 中:
- created_at DATETIME NULL DEFAULT NULL
- updated_at DATETIME NULL DEFAULT NULL
不能加 NOT NULL,也不能设 CURRENT_TIMESTAMP 类型的默认值,否则插入空值会失败或被自动填充。
模型 rules():显式允许为空
在模型的 rules() 方法中,为时间字段添加 'required' 的例外:
- [['created_at', 'updated_at'], 'safe'] —— 表示不参与验证,可为空或任意值
- 或更精准地:[['created_at', 'updated_at'], 'default', 'value' => null],配合 behavior 使用时更可控
避免写成 'required' 规则,否则 save() 会因字段为空报验证错误。
TimestampBehavior 配置:value 回调主动返回 null
行为本身默认不处理 null,需手动控制。在 behaviors() 中这样写:
- 'createdAt' => [ 'class' => TimestampBehavior::class, 'attribute' => 'created_at', 'value' => function () { return null; }, ]
- 'updatedAt' => [ 'class' => TimestampBehavior::class, 'attribute' => 'updated_at', 'value' => function () { return null; }, ]
这样新建记录时字段保持 NULL;若想“仅更新时填充、新增时不填”,可对 createdAt 用 'createdAtAttribute' => false 关闭自动填充,再单独配 updatedAt 行为。
额外注意:loadDefaultValues 和数据库默认值要关掉
如果开启了 ActiveRecord::loadDefaultValues = true,或数据库字段有 DEFAULT CURRENT_TIMESTAMP,它们会和你的 null 意图冲突。
- 在模型类顶部加:public $loadDefaultValues = false;
- 迁移或建表语句中,去掉字段的
DEFAULT定义


















