【问题标题】:Laravel validation unique failing on update for array of objectLaravel 验证唯一的对象数组更新失败
【发布时间】:2020-03-30 12:22:24
【问题描述】:

我有一个 API 可以发送一组人员,一些是需要更新的现有对象,一些是需要创建的新对象,它们都需要验证,其中一部分是测试一个唯一的电子邮件。我正在使用 FormRequest:

  $rules = [
        'staff.*.name' => 'required|max:128',
        'staff.*.email' => 'required|email|unique:users',
        'staff.*.description' => 'max:512',            
    ];

所以问题是,我相信您可以看到,电子邮件地址在更新时无法通过唯一验证。这是因为如果 ID 与正在验证的项目相同,则忽略电子邮件的机制会导致我出现问题。

我看不到获取当前正在验证的对象 ID 的方法,因此我可以访问其 ID。所以我不能添加部分:

'staff.*.email' => 'required|email|unique:users,email,id,' . $currentStaff->id

我对这个特定问题看不到太多,所以我假设我这样做是在找错树,或者错过了一些非常明显的东西。

下面的payload:

{
"staff": [
    {
        "name":"Libbie Turcotte",
        "email":"carolyn16@example.net",
        "updated_at":"2019-12-05 19:28:59",
        "created_at":"2019-12-05 19:28:59",
        "id":53
    },
    {
        "name":"Person Dave",
        "email":"dave@email.com",
    },
    {
        "name":"Staff Name",
        "email":"staff@email.com",

    }
  ]
}

【问题讨论】:

  • 这是可行的,但需要一些自定义逻辑,特别是在staff[] 输入数组中的某处包含ID,可以是staff[id]staff[][id]。并且规则需要根据输入来构建,所以你可以循环它并引用:foreach($request->input('staff') AS $staff){ ... // use $staff['id'] },或foreach($request->input('staff') AS $id => $staff){ ... // use $id }。如果您可以显示发送staff 输入的表单/ajax 请求,那将有所帮助。
  • 我明白你在说什么。员工 json 相当简单,我会更新我的问题以包含它。
  • 感谢您提供!下面的答案实际上正是在展示我所解释的内容;根据输入构建规则,可以看到123有不同的唯一规则,因为id的包含/省略。
  • 是的,现在只是实施该解决方案。说得通。感谢您在这方面的帮助。
  • phpunit tests/Feature/API/StaffTest.php --filter testAddAndUpdateStaff PHPUnit 8.4.3,作者 Sebastian Bergmann 和贡献者。 . 1 / 1 (100%)

标签: arrays laravel validation unique


【解决方案1】:

您可以为每个请求人员元素添加规则,遍历数组并合并相应的规则:

$rules = [  // this ones are ok for all
    'staff.*.name' => 'required|max:128',
    'staff.*.description' => 'max:512',
];
// here loop through the staff array to add the ignore
foreach($request->staff as $key => $staff) {
    if ( array_key_exists('id', $staff) && $staff['id'] ) { // if have an id, means an update, so add the id to ignore
        $rules = array_merge($rules, ['staff.'.$key.'.email' => 'required|email|unique:users,id,'.$staff['id']]);
    } else {  // just check if the email it's not unique
        $rules = array_merge($rules, ['staff.'.$key.'.email' => 'required|email|unique:users']);
    }
}

所以,对于这个请求

staff[1][id]=111
staff[1][email]=dd@ddd.dd
staff[2][id]=222
staff[2][email]=eee@eee.ee
staff[3][email]=fff@ffff

你会有这样的规则:

[
    "staff.*.name" => "required|max:128",
    "staff.*.description" => "max:512",
    "staff.1.email": "required|email|unique:users,id,111",
    "staff.2.email": "required|email|unique:users,id,222",
    "staff.3.email": "required|email|unique:users"
]

【讨论】:

  • 谢谢,很有魅力!对规则的小修改: $rules = array_merge($rules, ['staff.'.$key.'.email' => 'required|email|unique:users,id,' . $staff['id']] );
  • 哦!感谢您的反馈,我错过了。答案已更新;-)
【解决方案2】:

你可以只使用'distinct' 比如:

'staff.*.email' => 'distinct',

【讨论】:

    猜你喜欢
    • 2019-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-20
    • 2014-06-28
    • 1970-01-01
    • 2021-09-16
    • 1970-01-01
    相关资源
    最近更新 更多