插件窝 干货文章 ThinkPHP模型setInc/setDec方法更新数据时,updateTime字段为何不自动更新?

ThinkPHP模型setInc/setDec方法更新数据时,updateTime字段为何不自动更新?

字段 更新 updateTime 方法 962    来源:    2025-03-13

在ThinkPHP框架中,setIncsetDec 方法用于对数据库中的某个字段进行自增或自减操作。这两个方法在执行时,默认情况下不会自动更新 updateTime 字段(或其他时间戳字段),因为它们是通过直接生成SQL语句来更新数据库的,而不是通过模型的 save 方法。

原因分析

  1. 直接生成SQLsetIncsetDec 方法是通过生成类似 UPDATE table SET field = field + 1 WHERE ... 的SQL语句来直接更新数据库的。这种方式绕过了模型的 save 方法,因此不会触发模型的自动时间戳更新机制。

  2. 自动时间戳更新机制:在ThinkPHP中,模型的 save 方法会自动更新 updateTime 字段(如果模型配置了自动时间戳)。但是 setIncsetDec 方法并不会调用 save 方法,因此不会触发这个机制。

解决方案

如果你希望在执行 setIncsetDec 方法时自动更新 updateTime 字段,可以通过以下几种方式实现:

1. 手动更新 updateTime 字段

在执行 setIncsetDec 方法后,手动调用 save 方法来更新 updateTime 字段。

$model->where('id', $id)->setInc('field');
$model->where('id', $id)->save(['updateTime' => time()]);

2. 使用 update 方法替代 setIncsetDec

你可以使用 update 方法来替代 setIncsetDec,并在更新时手动更新 updateTime 字段。

$model->where('id', $id)->update([
    'field' => Db::raw('field + 1'),
    'updateTime' => time(),
]);

3. 使用数据库触发器

如果你不想在代码中手动处理 updateTime 字段的更新,可以考虑在数据库层面使用触发器来实现自动更新。

CREATE TRIGGER update_time_trigger
BEFORE UPDATE ON your_table
FOR EACH ROW
SET NEW.updateTime = NOW();

4. 扩展 setIncsetDec 方法

你可以通过继承模型类并重写 setIncsetDec 方法,使其在更新字段的同时更新 updateTime 字段。

class MyModel extends Model
{
    public function setInc($field, $step = 1)
    {
        $this->where('id', $this->id)->update([
            $field => Db::raw("{$field} + {$step}"),
            'updateTime' => time(),
        ]);
    }

    public function setDec($field, $step = 1)
    {
        $this->where('id', $this->id)->update([
            $field => Db::raw("{$field} - {$step}"),
            'updateTime' => time(),
        ]);
    }
}

总结

setIncsetDec 方法默认不会自动更新 updateTime 字段,因为它们直接生成SQL语句来更新数据库。你可以通过手动更新、使用 update 方法、数据库触发器或扩展模型类的方式来实现自动更新 updateTime 字段的需求。