2

So I have an array of data (not necessary coming from a $request)

       $validator = Validator::make($array, [
           '*.client_name' => 'required',
           '*.client_phone' => ['required ', 'regex:/^(0)(5|6|7)[0-9]{8}/'],
       ]);

       $validator->validate();

So far, validation messages shows as

The field 1.client_name is required

I want something like

Row 1 : The field client_name is required

If I use $validator->setAttributeNames($newAttributeNames); I lose row number from the wildcard(*) even if I set teh wildcard in the new attribute name.

Also note that I don't want to override messages of all the rules provided by laravel (here are 2 examples but irl I have many rules)

So any idea how to accomplish this ?

2 Answers 2

2

The best approach I could find so far is inspired from @Tim Welis answer but using loops instead

$rules = [
    '*.client_name' => 'required',
    '*.client_phone' => ['required ', 'regex:/^(0)(5|6|7)[0-9]{8}/'],
    '*.age' => 'required | numeric | between:0,100',
];

$messages = [];
foreach($array as $rowNum => $row)
{
    foreach($row as $field => $value) {
        $messages["{$rowNum}.".$field.'.required'] = "Row {$rowNum} : The field {$field} is required";
        $messages["{$rowNum}.".$field.'.regex'] = "Row {$rowNum} : The field {$field} format is invalid";
        $messages["{$rowNum}.".$field.'.numeric'] = "Row {$rowNum} : The field {$field} must be numeric";
        $messages["{$rowNum}.".$field.'.between'] = "Row {$rowNum} : The field {$field} value must be between :min - :max";
    }
}

$validator = Validator::make($array, $rules, $messages);
$validator->validate();   

The rule message is written only once for all the attributes

Sign up to request clarification or add additional context in comments.

Comments

1

An approach I generally use is dynamic validation; from your uploaded input, construct the $rules and $messages:

$rules = [];
$messages = [];
for($i = 0; $i <= count($array); $i++){
  // Since arrays are 0-based, 0 will be Row 1, etc.
  // If you want index 0 to be Row 0, then just use `$i` below
  $rowNum = $i + 1; 

  $cnKey = "{$i}.client_name";

  $rules[$cnKey] = 'required';
  $messages["{$cnKey}.required"] = "Row {$rowNum}: The field client_name is required";

  $cpKey = "{$i}.client_phone";

  $rules[$cpKey] = ['required', 'regex:/^(0)(5|6|7)[0-9]{8}/'];
  $messages["{$cpKey}.required"] = "Row {$rowNum}: The field client_phone is required";
  $messages["{$cpKey}.regex"] = "Row {$rowNum}: The field client_phone format is invalid";
}

$validator = Validator::make($array, $rules, $messages);
$validator->validate();

This discards the wildcards, and uses 0.client_name, 0.client_phone, etc etc explicitly, and allows you to construct unique validation messages on the fly.

2 Comments

Although this solution is working, it's quite painful to write, especially when you have too many attributes and rules. I posted an answer inspiring from your solution
Perfect! I totally agree; this approach works for a couple, simple validation rules, but isn't the most DRY (don't repeat yourself) solution. I'm glad you were able to come up with something that worked for you :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.