广告

Laravel Eloquent update方法详解与使用教程:从基础到实战的完整指南

本文聚焦 Laravel Eloquent update 方法,带你从基础到实战完整掌握更新数据的设计与实现要点,帮助开发者提升开发效率与代码质量。通过系统化的示例和实战场景,深入理解Laravel Eloquent update 方法的工作原理、用法差异以及在实际项目中的最佳实践。

一、Laravel Eloquent update 方法的工作原理

更新机制与模型状态

Eloquent 中,update() 可以通过模型实例或查询构建器执行,核心在于将待更新的属性批量赋值后,生成一条 UPDATE 语句并执行。通过模型实例的 update(),更新会触发模型的事件流(如 updating/updated),同时保持时间戳字段的自动更新。

当我们使用 模型实例($model->update(...)) 时,Eloquent 会先将传入的属性进行赋值,然后调用 save() 实现持久化,整个过程会触发模型事件和属性的变更检测。

title = '新标题';
$model->content = '更新后的内容';
$model->update(); // 等价于 $model->save()
?>

更新时的属性填充与守卫

要让 update() 正常工作,必须确保被批量赋值的字段在模型中被明确允许,即通过 fillable 进行白名单,或通过 guarded 配置进行全局保护。

在实际场景中,protected $fillable 用于列出可以批量赋值的字段,protected $guarded 用于列出不可批量赋值的字段。这些配置直接影响到 安全性与更新行为

与查询构建器的 update 区别

当通过查询构建器执行更新(如 Post::where(...)->update(...)),更新将直接在数据库层完成,不会触发 模型事件,也不会自动处理时间戳。

因此,使用查询构建器的 update 更适合批量无模型状态下的更新场景,但需要手动管理 时间戳 与事件逻辑。

关键点小结

综上所述,update 在模型实例上会保持事件流与时间戳行为,而在查询构建器上执行时则更高效但缺少事件与自动时间戳的触发,需要开发者自行处理相关逻辑。

二、更新单个模型实例的数值字段

通过属性赋值再调用 save()

要更新单个模型实例,可以先读取模型、修改需要更新的属性,然后调用 save() 完成持久化,这对于需要在更新前进行复杂逻辑的场景非常直观。

该方式会触发模型事件(如 updatingupdated),并且遵循 filled 与时间戳的规则。

使用 update() 的快捷方式

也可以直接通过 $model->update([...]) 的快捷方式进行多字段更新,该方法返回布尔值,表示是否更新成功。

实际使用中,更新结果的布尔返还可以用于控制后续逻辑,例如缓存刷新或用户提示。

title = '更新后的标题';
$post->content = '更新后的内容';
$post->update(['title' => $post->title, 'content' => $post->content]);
?> 

注意模型事件与数据验证

在通过模型实例进行 update 时,务必关注 模型事件 的触发顺序,以及在更新前后的数据校验与业务规则。

另外,如果使用 mass assignment,应确保字段在 $fillable 中被允许,避免抛出 MassAssignmentException

Laravel Eloquent update方法详解与使用教程:从基础到实战的完整指南

三、批量更新与查询构建器的 update

批量更新的语义与性能

批量更新通常使用查询构建器来完成(如 Post::where(...)->update(...)),它比逐条加载模型再逐条调用 save() 更高效,尤其是在处理大量数据时。

需要注意的是,批量更新不会触发任何 Eloquent 的模型事件,也不会自动处理 更新时间 字段,除非显式在更新语句中设置。

返回值与事件触发

查询构建器的 update() 返回受影响的行数(int),这对于统计与日志记录很有用。事件触发方面,批量更新不会调用模型的 updating/updated 等事件。

因此,在需要事件驱动逻辑时,优先使用模型实例的更新路径,否则需要在代码中自行处理相关行为。

update(['status' => 'published', 'updated_at' => now()]);
// $affected 是更新的行数
?> 

四、实战案例:带条件的更新与乐观锁实现

带条件的更新示例

在实际业务中,通常需要在特定条件下才执行更新,例如只有当库存大于 0 时才将其减 1。

这类场景建议使用查询构建器实现原子性更新,以避免并发问题并提升性能。

乐观锁实现思路与代码

乐观锁通过版本号字段来检测并发修改。常见做法是在表中增加一个 version 字段,在更新时携带当前版本号并在 where 条件中对比版本号,实现乐观锁。

下面给出一个简单的示例,展示如何在更新前检查版本号并在成功提交时自增版本号。

version === $expectedVersion) {$post->title = '乐观锁更新后的标题';$post->version = $post->version + 1;$post->save();
} else {// 版本不匹配,处理并发冲突
}
?> 

五、更新策略与性能优化

Upsert 与 updateOrCreate 的使用场景

在需要“如果存在就更新,否则插入”的场景中,upsertupdateOrCreate 提供便捷解决方案,避免手动查找再决定更新或新增。

Laravel 的 Model::upsert() 与查询构建器的 upsert() 支持多列联合唯一键的更新,因此在需要去重和批量写入时非常有用。

 'jane@example.com', 'name' => 'Jane', 'votes' => 0],
], ['email'], ['name', 'votes']);
?> 

事件触发与性能取舍

需要注意的是,使用 query builder 的 upsert 时不会触发模型事件,因此如果你依赖于事件完成一些副作用,请谨慎使用或者在前置/后置逻辑中手动实现。

在对高并发场景进行更新时,优先考虑原子操作与数据库层级锁机制,以实现最小的锁粒度和更高的吞吐量。

 1, 'title' => '首条', 'views' => 10],['id' => 2, 'title' => '第二条', 'views' => 5],
], ['id'], ['title', 'views']);
?> 

广告

后端开发标签