Laravel sometimes validation on arrays
Couldn't get sometimes()
to work in a way you need. sometimes()
doesn't "loop" over array items, it gets called a single time.
I came up with an alternative approach, which isn't perfect, but maybe you'll find it useful.
/** * 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' ];}
Curious to learn how this could be improved.
The shortest approach I could get to work is this:
"items" => "required|array","items.*.age" => "required|integer","items.*.father" => "required_if:object.*.age,".implode(",",range(0,18))."|min:5"
Anytime a father is needed for that person, it should be having at least 5 characters. A father is needed when the person's age is below 18.
required_if
works with multiple equations separated with commas. Therefore I wrote 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18
as implode(',',range(0,18))
to get that part.
The test setup I've used:
Controller (used 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()); }}
View (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
Routes
Route::view("/test", "test");Route::post('/posttest', "HomeController@posttest");