在 laravel 中,当子模型(如 comment)更新时,可通过 `touches` 属性自动更新直接父模型(如 post)的 `updated_at`;若需进一步更新“祖父级”模型(如 user),需结合模型事件手动触发 `touch()`,本文详解实现方法与最佳实践。
在 Laravel 的 Eloquent ORM 中,$touches 属性仅支持单层向上触达——即子模型更新时自动调用其直接关联父模型的 touch() 方法。例如,Comment 模型设置 protected $touches = ['post'],可在评论更新时自动刷新对应 Post 的 updated_at;但该机制不会递归生效,因此在 Post 模型中声明 protected $touches = ['user'] 并不能使 User 时间戳随 Comment 更新而变更。
要实现跨两级的级联时间戳更新(如 Comment → Post → User),推荐采用 Eloquent 模型事件 + 显式 touch() 调用 的组合方案。核心思路是:在中间模型(Post)监听自身 updated 事件,并主动触达其关联的 User 模型。
以下为具体实现步骤:
belongsTo(User::class);
}
/**
* 模型启动时注册事件监听器
*/
protected static function booted()
{
static::updated(function (self $post) {
// 确保关联关系存在且未软删除,避免异常
if ($post->user && ! $post->user->trashed()) {
$post->user->touch();
}
});
}
}? 说明:static::updated() 是静态闭包监听器,在每次 Post 实例被成功更新后执行;$post->user->touch() 会更新该用户的 updated_at(仅限 updated_at 字段,默认不修改 created_at)。
// 创建用户、文章、评论 $user = User::create(['name' => 'Alice']); $post = $user->posts()->create(['title' => 'Hello']); $comment = $post->comments()->create(['body' => 'First comment']); // 初始时间戳 dump($user->updated_at); // 2025-01-01 10:00:00 dump($post->updated_at); // 2025-01-01 10:00:05 // 更新评论 → 触发 Post::touches → 更新 Post.updated_at $comment->update(['body' => 'Updated comment']); // 此时 Post.updated_at 变更,同时因 Post::updated 事件触发,User.updated_at 也同步更新 dump($user->fresh()->updated_at); // 2025-01-01 10:00:10 ← 已更新!
通过上述方式,你即可精准、可靠地实现 Laravel 中任意深度的父模型时间戳级联更新。