Laravel有时对数组进行验证

时间:2018-11-30 09:54:30

标签: laravel validation

假设我们具有以下表单数据:

{age: 15, father: "John Doe"}

我们想要基于同一项目的其他数据来验证father字段背后有一些复杂的逻辑(对于此示例,我们希望在年龄<18岁时验证父亲至少有5个字符)。 / p>

可以这样做:

Standard validation rules: ['age': 'required|integer']

$validator->sometimes('father', 'required|min:5', function($data) {
    return $data['age'] < 18;
});

现在,我们希望将相同的东西与项目列表一起使用。现在,我们有了以下表单数据:

[
  {age: 25, },
  {age: 15, father: "John Doe"},
  {age: 40, },
]

通用验证规则现在看起来像这样:

['items.*.age': 'required|integer']

我现在的问题是轻松地为每个项目的sometimes字段表达father规则,这取决于项目的age字段。

$validator->sometimes('items.*.father', 'required|min:5', function($data) {
    // Does not work anymore: return $data['age'] < 18;
    // Any way to know which item we are dealing with here?
});

我想到的一种方法是遍历验证器after回调中的项目。但这似乎不是很优雅:(

2 个答案:

答案 0 :(得分:2)

无法使sometimes()以您需要的方式工作。 sometimes()不会“遍历”数组项,它被称为一次。

我想出了另一种方法,虽然它并不完美,但是也许您会发现它有用。

/**
 * Get the validation rules that apply to the request.
 *
 * @return array
 */
public function rules()
{
    Validator::extend('father_required_if_child', function ($attribute, $value, $parameters, $validator) {

        $childValidator = Validator::make($value, [
            'age' => 'required|integer'
        ]);

        $childValidator->sometimes('father', 'required|min:5', function($data) {
            return is_numeric($data['age']) && $data['age'] < 18;
        });

        if (!$childValidator->passes()) {
            return false;
        }

        return true;

        // Issue: since we are returning a single boolean for three/four validation rules, the error message might
        // be too generic.

        // We could also ditch $childValidator and use basic PHP logic instead.
    });

    return [
        'items.*' => 'father_required_if_child'
    ];
}

好奇地了解如何进行改进。

答案 1 :(得分:1)

我可以使用的最短的方法是:

"items" => "required|array",
"items.*.age" => "required|integer",
"items.*.father" => "required_if:object.*.age,".implode(",",range(0,18))."|min:5"

该人每次需要父亲时,其至少应有5个字符。 该人的年龄在18岁以下需要父亲。

required_if适用于多个用逗号分隔的方程式。因此,我将0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18写为implode(',',range(0,18))来获得这一部分。

我使用的测试设置:

控制器(用于HomeController)

function posttest(Request $request) {
    $validator = Validator::make($request->all(), [
        "object" => "required|array",
        "object.*.age" => "required|integer",
        "object.*.father" => "required_if:object.*.age,".implode(",",range(0,18))."|min:5"
    ]);

    if($validator->fails()){
        dd($validator->errors());
    }
}

查看(test.blade.php)

@extends('layouts.app')
@section('content')
<form action="{{URL::to("/posttest")}}" method="POST">
@csrf
<input type="number" name="object[0][age]" value="12">
<input type="text" name="object[0][father]" value="John">
<input type="number" name="object[1][age]" value="15">
<input type="text" name="object[1][father]" value="John Doe">
<input type="number" name="object[2][age]" value="17">
<input type="submit" value="gönder">
</form>
@endsection

路线

Route::view("/test", "test");
Route::post('/posttest', "HomeController@posttest");