【问题标题】:Laravel request update unique field only if changedLaravel 请求仅在更改时更新唯一字段
【发布时间】:2018-12-25 00:20:36
【问题描述】:

我无法根据某些情况验证用户电子邮件地址。

例如

如果正在创建用户,则电子邮件地址必须是唯一的

如果用户正在更新但电子邮件地址未更改,则忽略唯一电子邮件规则

如果用户正在更新并且他们的电子邮件地址已更改,则它必须是唯一的

我环顾了一下,我知道我可以根据这样的方法指定不同的规则

public function rules()
{
    $user = User::find($this->users);

    switch($this->method())
    {
        case 'POST':
        {
            return [
                'user.email'      => 'required|email|unique:users,email',
            ];
        }
        case 'PUT':
        case 'PATCH':
        {
            return [
                'user.email'      => 'required|email,
            ];
        }
        default:break;
    }
}

有什么方法可以让在 put/patch 情况下,规则检查电子邮件地址是否已更改,如果已更改,则它必须是唯一的?

如果没有,是否有更清洁的方法来实现这一目标?也许没有开关盒?也许我还没有偶然发现更深入的验证规则?

【问题讨论】:

  • 我添加了一个答案,检查一次
  • @rkj 我听取了另一个用户的建议,暂时删除了 switch 语句以尝试清理代码。如果我重新使用 switch 方法,我会尝试你的答案,谢谢。
  • 不需要为我的答案添加开关条件,一行将适用于所有创建,补丁
  • 抱歉,我没有注意到您已将其更新为忽略 switch 语句。你的回答很好,谢谢!
  • 很高兴它对你有用

标签: php laravel validation laravel-5 request


【解决方案1】:

我遇到了类似的问题,并在文档中找到了一种解决问题的简洁方法。

我的问题是,如果用户已经创建,电子邮件地址声称它不是唯一的,即使它已经注册给用户。

https://laravel.com/docs/8.x/validation#rule-unique

下面的几个标题是这样的:

use Illuminate\Validation\Rule;

$request->validate([
    'email' => [
        'required',
        Rule::unique('users')->ignore($user->id),
    ],
]);

执行以下操作:

验证电子邮件地址,使其成为必填且唯一,除非该行的用户 ID 与该用户匹配。

【讨论】:

    【解决方案2】:

    你可以试试这个

    $exists = Section::where('code', $request->code)->exists();
            $isUpdateQuery = (($request->method() == 'PUT') || ($request->method() == 'PATCH'));
            $validatedData = $request->validate([
                "code" => ['required','unique:sections,code' . (($isUpdateQuery && $exists) ? ',' . $request->code . ',code': '')],
                "title" => 'required | json',
                "subtitle" => 'required | json',
                "btn_title" => 'required | json',
                "name" => 'required',
                "pageID" => 'required | exists:pages,pageID',
                "image" => 'nullable',
                "btn_link" => 'nullable',
            ]);
    

    【讨论】:

      【解决方案3】:

      我的方式:

      'slug' => $site->slug !== $request->slug ? 'required|min:4|max:80|unique:sites' : 'required|min:4|max:80'
      

      【讨论】:

        【解决方案4】:
        $request->validate([
                'naam' => 'required|max:190|unique:database_name.table,column_where_you_check_unique,'.$id.',$id_column_reference'
            ]);
        

        'naam' - 表单输入字段名称

        database_name(可选) - 如果你有多个数据库

        table(required) - 表名

        column_where_you_check_unique(必需)- 数据是唯一的

        $id(required) - 使用 id 自动增量检查

        $id_column_reference - $id 的列名。

        【讨论】:

          【解决方案5】:

          为此有一个内置功能。您可以将实际用户 ID 添加到唯一约束(如果存在)。这将确保唯一约束仍然有效,但在值未更改时不会失败:

          $exists = $user->exists;
          $rules = return [
              'user.email' => 'required|email|unique:users,email' . ($exists ? ','.$user->id : ''),
          ];
          

          在内部,这将执行如下查询:

          SELECT count(id) FROM users WHERE email = 'some-mail@example.com' AND id != 42
          

          后半部分AND id != 42 只会在您将第三个参数添加到唯一验证规则时作为查询的一部分。

          【讨论】:

          • 这听起来合乎逻辑,但它似乎对我不起作用?如果我不更改它,它仍然会错误地说电子邮件必须是唯一的。这是否必须在上述switch 声明中应用,还是只能作为一般规则?
          • 如果除了独特的东西之外没有其他充分的理由使用开关,请摆脱它 - 对于独特的约束,您绝对不需要它。您只需要一种良好且一致的方法来确定用户是否已经存在。顺便说一句,我不得不修复对$user->exists 的调用,因为它不应该是函数调用。这是一个神奇的属性。
          • 它似乎仍然没有正确检测,它仍然返回'电子邮件已被占用'
          • @S_R 你试过我的回答了吗?
          【解决方案6】:

          如果我对您的理解正确,您想在电子邮件更改时添加unique 验证,如果是这种情况,那么您只需要在验证中添加一个条件。如果你检查独特的验证结构,它看起来像这样unique:table,column,except,idColumn,检查documentation

          因此验证将如下所示,当您创建新记录时,$userId 将为空,但在修补时它将具有价值。所以这个验证对 create 和 patch 都有效。

          $userId = isset($user) ? $user->id : null;
          
          $rules = [
                  'email' => 'required|email|unique:users,email,'. $userId.',id',
              ];
          
           $this->validate($request, $rules);
          

          【讨论】:

            【解决方案7】:

            您在每个case. 之后都缺少break; 语句,对于更新(PATCH 请求),您还必须在更新请求中传递id

            public function rules()
            {
                $user = User::find($this->users);
            
                switch($this->method())
                {
                    case 'PATCH':
                    {
                        return [
                            'user.email'      => 'required|email|unique:users,email,'. $user->id.',id',
                        ];
                    }
                    break; // change here
                    case 'PUT': break; // change here
                    case 'POST':
                    {
                        return [
                            'user.email'      => 'required|email,
                        ];
                    }
                    break; // change here
                    default:break;
                }
            }
            

            【讨论】:

              【解决方案8】:

              在您的控制器方法(存储和更新)中,您可以使用:

               $validations = [
                      'email'                 => 'required|email|unique:users,email'
                  ];
              
               $this->validate($request, $validations);
              

              【讨论】:

              • 对不起,我很想知道这如何回答我的问题?这与我请求中的 switch 方法相同,我需要它能够检测 POST 中的电子邮件是否已更改,如果已更改,则运行不同的唯一规则
              • 你有更多的代码、控制器、模型和/或存储库吗?
              猜你喜欢
              • 1970-01-01
              • 2019-11-11
              • 2018-07-05
              • 2018-08-09
              • 2020-07-11
              • 1970-01-01
              • 1970-01-01
              • 2020-04-26
              • 2016-11-10
              相关资源
              最近更新 更多