返回

避免 Eloquent 字段意外更新的陷阱:两种有效方法

mysql

避免 Eloquent 字段意外更新的陷阱

简介

在使用 Laravel Eloquent 执行数据库更新操作时,我们可能遇到意外字段更新的问题,导致不仅更新了指定的字段,还更新了我们不希望更新的字段。这可能会破坏应用程序的完整性,导致难以调试的错误。在本文中,我们将探讨此问题的原因并探讨如何使用两种方法来解决它。

问题根源

当使用 Eloquent 的 update() 方法更新模型时,它会自动更新模型中所有已填充的字段,包括那些未在 $fillable 数组中指定的字段。这可能是导致意外字段更新的原因,尤其是当模型中存在访问器或突变器(即 getRequestedAtAttribute()setRequestedAtAttribute())时。在这种情况下,即使 request_at 字段未包含在模型的 $fillable 数组中,它仍被视为已填充字段,因此会被自动更新。

解决方案

要解决意外字段更新的问题,有两种有效的方法:

方法 1:使用 Mass Assignment Protection

Eloquent 提供了大规模赋值保护机制,可防止自动更新未包含在 $fillable 数组中的字段。要启用此保护,请在模型中添加以下属性:

protected $guarded = ['*'];

这样,只有包含在 $fillable 数组中的字段才能在更新操作中更新,从而防止意外字段更新。

方法 2:使用 RAW SQL 查询

另一种方法是直接使用 RAW SQL 查询来执行更新操作,绕过 Eloquent 的自动更新机制。这可以通过使用 DB 外观来实现:

DB::table('stock_recharges')
    ->whereNull('deleted_at')
    ->where('status_id', StatusRepository::getByName('ACTIVE'))
    ->whereRaw('DATEDIFF(CURDATE(), requested_at) = 4')
    ->update(['status_id' => StatusRepository::getByName('EXPIRING')]);

使用 RAW SQL 查询提供了对更新过程的更多控制,允许我们明确指定要更新的字段,从而避免意外更新。

结论

理解并解决 Eloquent 中意外字段更新的问题对于确保应用程序的稳定性和数据的完整性至关重要。通过使用大规模赋值保护或直接使用 RAW SQL 查询,我们可以有效地防止意外字段更新并确保更新操作只影响所需的字段。

常见问题解答

  1. 为什么 Eloquent 会自动更新所有已填充的字段?

    Eloquent 旨在简化模型的更新过程,通过自动更新所有已填充的字段,它可以节省开发人员明确指定每个要更新字段的麻烦。

  2. 访问器和突变器如何影响意外字段更新?

    访问器和突变器是属性,它们允许我们修改模型字段的获取和设置行为。当存在访问器或突变器时,即使字段未包含在 $fillable 数组中,Eloquent 仍将其视为已填充字段,因此在更新操作中会被自动更新。

  3. 什么时候应该使用大规模赋值保护?

    大规模赋值保护适用于需要严格控制更新哪些字段的情况。例如,在处理敏感数据或具有复杂数据模型时,它可以防止意外数据更改。

  4. 什么时候应该使用 RAW SQL 查询?

    当需要对更新过程有更精细的控制时,或者当使用 Eloquent API 难以实现所需的更新时,应该使用 RAW SQL 查询。它允许我们指定确切的要更新的字段并避免意外更新。

  5. 如何防止其他意外更新场景?

    除了解决意外字段更新问题之外,还应该采取其他措施来防止意外更新,例如使用适当的访问权限控制、进行单元测试和在更新操作之前仔细审查代码。