文章浏览量、点赞数这类字段做自增时,很多人都会直接调用 Laravel 的 increment()。但在实际项目里,这种写法往往会顺手把 updated_at 一起改掉,结果导致“内容最后更新时间”失真。下面就从 Eloquent 的判断逻辑入手,看看它为什么会更新这个字段,以及怎样在不改动整体模型设计的前提下,让某次自增跳过时间戳更新。
为什么 increment() 会改动 updated_at
问题最常见的场景,是文章浏览量自增:

$article->increment('views', 1);
这段代码看起来只是把 views 加 1,但实际执行后,Laravel 还会自动更新 updated_at。如果这个字段在你的业务里代表“文章内容最近修改时间”,那浏览一次就刷新一次显然不合理。
继续往下看源码,可以发现 Eloquent 在更新时会先判断当前模型是否启用了时间戳机制。相关逻辑在源码中大致如下:
// vendorlaravelframeworksrcIlluminateDatabaseEloquentBuilder.php
/**
* Add the "updated at" column to an array of values.
*
* @param array $values
* @return array
*/
protected function addUpdatedAtColumn(array $values)
{
if (! $this->model->usesTimestamps() ||
is_null($this->model->getUpdatedAtColumn())) {
return $values;
}
$column = $this->model->getUpdatedAtColumn();
$values = array_merge(
[$column => $this->model->freshTimestampString()],
$values
);
$segments = preg_split('/s+ass+/i', $this->query->from);
$qualifiedColumn = end($segments).'.'.$column;
$values[$qualifiedColumn] = $values[$column];
unset($values[$column]);
return $values;
}
这里的关键判断是 usesTimestamps()。只要模型启用了时间戳,并且定义了 updated_at 字段,Laravel 就会把新的时间写进去。
源码里真正的判断依据是什么
再看 usesTimestamps() 的实现,会更直接一些:
/**
* Determine if the model uses timestamps.
*
* @return bool
*/
public function usesTimestamps()
{
return $this->timestamps;
}
也就是说,这个行为最终取决于模型上的 timestamps 属性。只要它为 true,类似 increment() 这样的更新操作就会带上 updated_at。
这也解释了为什么很多人会遇到这个问题:模型本身通常需要时间戳,不能简单地把 public $timestamps = false; 永久关掉;但某些特定操作,比如浏览量、热度值、计数器更新,又确实不希望触发更新时间变化。
一个更适合业务场景的处理方式
既然判断条件是 timestamps,那思路就很明确了:只在当前这次操作前临时把它关掉。为了不把这段逻辑散落在各个模型里,可以抽成一个 trait:

<?php
namespace AppTraits;
trait UpdateWithoutUsesTimestamps
{
/**
* Determine if the model uses timestamps.
*/
public function notUsesTimestamps()
{
$this->timestamps = false;
return $this;
}
}
这个 trait 做的事情很简单:提供一个 notUsesTimestamps() 方法,在链式调用前把当前模型实例的 timestamps 设为 false。
然后在对应的模型中引入它:
<?php
namespace App;
use AppTraitsUpdateWithoutUsesTimestamps;
use IlluminateDatabaseEloquentModel;
class Article extends Model
{
use UpdateWithoutUsesTimestamps;
}
这样一来,模型默认仍然保留 Laravel 的时间戳行为,只有在你明确调用这个方法时,才会跳过本次更新时间写入。
自增时应该怎么调用
实际使用时,把原来的自增写法替换成下面这样即可:
$article->notUsesTimestamps()->increment('views', 1);
这样执行后,views 会正常加 1,但不会自动更新 updated_at。
这个方案比较适合以下场景:
- 文章浏览量自增
- 点赞数、收藏数、评论计数更新
- 不应影响“内容最后修改时间”的统计字段维护
如果你的业务需要严格区分“内容编辑”与“行为计数变化”,这种做法会比直接关闭整个模型的时间戳更稳妥,也更容易控制影响范围。
使用这种写法时要注意什么
这个思路的优点是轻量、直接,几乎不需要改动原有模型结构;但它本质上还是通过修改模型实例上的 timestamps 属性来影响行为,因此更适合这种单次、明确的调用场景。
换句话说,它解决的是“某一次更新不想动 updated_at”的问题,而不是彻底改变模型的时间戳策略。对于资讯、内容管理、博客系统这类项目,这样的粒度通常已经够用:正常编辑文章时保留 updated_at,只有浏览量这类计数字段变化时才跳过更新,语义上也更清晰。













