【问题标题】:Laravel Validation with Soft Deleted Model and Unique DB field使用软删除模型和唯一数据库字段的 Laravel 验证
【发布时间】:2019-02-16 06:53:47
【问题描述】:

我正在努力思考如何处理这个用例。

我有一个具有唯一数据库字段(电子邮件)的用户模型。我也在使用软删除。

我需要处理三种情况:

1) 更新用户模型。目前我的验证阻止用户被更新,因为这封电子邮件已经存在。我认为如果电子邮件没有更改,则忽略电子邮件验证很容易解决这个问题。

2) 更新了不同的用户模型,并将电子邮件更改为数据库中已经存在的另一个电子邮件。

3) 创建了一个新模型,并且电子邮件已经存在于数据库中。

以上所有场景还必须考虑软删除模型。

有人对如何构建这个有一些建议吗?

【问题讨论】:

  • 我猜你会为自己打造 3 个不同的 FormRequests 并且可能会引入一些自定义规则。这就是我会做的。
  • 我在 Laravel 控制器公共方法存储和更新中处理了这一切。表单只是发送所有数据的一种表单。关于更新,表单字段预先填充了数据库中该用户的现有值。
  • 是的,将其移至 FormRequests,它将帮助您精简控制器,这就是我要做的。 注意:更新 FR 应该在rules() 中有某种逻辑来在更新自己和其他人之间切换。显然你不需要 3 个 FR,​​而是 2 个,我的错。祝你好运!
  • 听起来像一个计划,我会研究 FormRequests。谢谢!
  • 完成后,在此处发布 更新 FR,因为那将是最有问题的一个,我会用实际代码进一步帮助你(如果你这样做了在此期间不要自己弄清楚)。我还将 FR 命名为:UserUpdateRequestModelActionRequestModelAction,当然还可以使用 art make:request 命令。

标签: database laravel validation


【解决方案1】:

对于更新,您可以调整验证规则以在更新时忽略当前用户记录。规则签名是这样的:

'email' => 'unique:user,email,{$userId},id,deleted_at,NULL'

对于插入新的,这样的规则:

'email' => 'unique:user,email,NULL,NULL,deleted_at,NULL'

应该工作并忽略softDeleted 记录。如果您的数据库中有唯一键,if 仍然会失败。

当然,如果你还取消删除一条记录,你会有重复,这是 Laravel 无法阻止的。

【讨论】:

  • 谢谢!我感谢我收到的所有答案。因为我只能将一个标记为正确,所以我会公平地标记第一个。
  • 不用担心。无论如何,使用Rule 更好/更通用。我只是习惯于使用直弦。 :)
【解决方案2】:

您可以使用Rule::unique() 验证。如果您使用模型绑定,则从路由中取出您的用户模型,或者执行传统的数据库查询以通过 ID 取出用户(如果您传入一个)。然后您可以在验证中执行此操作。

这也应该适用于软删除模型。

return [
    'email' => Rule::unique('users', 'email')->ignore($user->email)->whereNull('deleted_at')->orWhereNotNull('deleted_at')
]

【讨论】:

  • 在 Laravel 7.0 中使用 ->withTrashed 在您的第二个示例中失败:ERROR: Call to undefined method Illuminate\Validation\Rules\Unique::withTrashed()
【解决方案3】:

对于 Laravel 8,上述解决方案不再起作用,可能是唯一的规则在以后改变了。

但是,您可以使用以下验证规则。

use Illuminate\Validation\Rule;

'email' => [
    'required',
    'email',
    Rule::unique('users', 'email')->where(function($query){
       return $query->whereNull('deleted_at')
         ->orWhereNotNull('deleted_at');
    })
]

【讨论】:

    【解决方案4】:

    在 Laravel 8 中,使用 withoutTrashed() 规则修饰符大大简化了它:

    use Illuminate\Validation\Rule;
    
    'email' => [
        'required',
        'email',
        Rule::unique('users', 'email')->withoutTrashed()
    ]
    

    L8 API 中提到了该方法:

    https://laravel.com/api/8.x/Illuminate/Validation/Rules/Unique.html#method_withoutTrashed


    是否还值得一提的是,在 L8 API 中也提到了 Rule::exists()->withoutTrashed()

    https://laravel.com/api/8.x/Illuminate/Validation/Rules/Exists.html#method_withoutTrashed

    【讨论】:

      猜你喜欢
      • 2017-06-02
      • 2019-08-13
      • 1970-01-01
      • 2013-07-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-24
      • 2021-07-07
      • 2021-10-15
      相关资源
      最近更新 更多