yii 1.1.26中activerecord需手动处理时间戳:推荐在rules()中用cdbexpression('now()')设default值(insert/update场景分离),或重写beforesave()赋值;须确保字段为datetime类型且声明safe。

在 Yii 1.1.26 中,ActiveRecord 默认不会自动填充 created_at、updated_at 等时间戳字段,需要手动干预。核心思路是:**不让时间戳依赖表单输入,而由模型自身在保存前生成**。以下是几种可靠、兼容性强的做法。
用 rules() 设置默认值(推荐)
这是最简洁且符合 Yii 1.1 风格的方式。在模型的 rules() 方法中,为时间戳字段添加 default 规则,并配合 CDbExpression('NOW()') 让数据库执行当前时间函数:
-
created_at在插入时设为NOW(),且仅作用于insert场景 -
updated_at在更新时设为NOW(),且仅作用于update场景 - 必须使用
CDbExpression,不能写成字符串'NOW()'或 PHP 函数如time(),否则会被当作文本插入
示例代码:
public function rules()
{
return array(
// 其他验证规则...
array('created_at', 'default', 'value' => new CDbExpression('NOW()'), 'on' => 'insert'),
array('updated_at', 'default', 'value' => new CDbExpression('NOW()'), 'on' => 'update'),
array('created_at, updated_at', 'safe'), // 避免被 mass-assignment 过滤掉
);
}
重写 beforeSave() 方法(灵活可控)
适合需要更精细控制的场景,比如统一用 datetime 格式、或根据业务逻辑跳过某些更新。注意要调用父类方法并返回布尔值:
- 判断
$this->isNewRecord区分新增/更新 - 直接赋值
new CDbExpression('NOW()'),确保数据库生成时间 - 不要用
date('Y-m-d H:i:s'),因为时区或服务器时间可能不准,且不利用数据库事务一致性
示例代码:
public function beforeSave()
{
if ($this->isNewRecord) {
$this->created_at = new CDbExpression('NOW()');
}
$this->updated_at = new CDbExpression('NOW()');
return parent::beforeSave();
}
确保数据库字段类型和模型属性匹配
手动设置时间戳的前提是底层支持:
- 数据库字段建议用
DATETIME类型(不是TIMESTAMP,避免 MySQL 自动更新行为干扰) - 模型中无需声明属性,AR 会自动映射;但若字段名不在数据库中,需检查表结构是否已同步
- 如果字段名为
create_time/modify_time等非标准命名,规则和赋值中必须严格对应
避免常见错误
这些做法看似合理,但在 Yii 1.1.26 下容易导致时间戳为空或出错:
- 在控制器里手动写
$model->updated_at = date('Y-m-d H:i:s');—— 时区易错,且绕过模型逻辑 - 把时间戳字段加进表单提交(如 hidden input),再靠
$_POST赋值 —— 安全风险高,且可能被 mass-assignment 过滤 - 只在
rules()里写了required却没配default—— 新增时因校验失败无法保存 - 忘记在
scenarios()或安全属性中放开时间戳字段 —— 尤其在自定义场景下,safe声明很关键











