Laravel validation min and regex being outputted to the same message - php

I'm having a bit of a weird issue and i'm not quite sure why its happening or if i'm just missing something.
I have multiple validation rules on a input 'postcode' field, like so
'postcode' => [
'required',
'min:5',
'max:8',
'regex:/^[a-z]/i'
],
And i've also wrote custom messages for the rules like so
return [
'postcode.min' => 'The postcode must be at least 5 characters',
'postcode.regex' => 'Sorry, the postcode must start with a letter',
];
All of my errors are being looped and displayed like this
<div class="error-block {{ (count($errors) > 0) ? '' : 'hide' }}">
<div class="col-12">
<ul>
#if(count($errors) > 0)
#foreach($errors->all() as $error)
<li>{{$error}}</li>
#endforeach
#endif
</ul>
</div>
</div>
But when both rules are hit for the postcode, for example with the input '123', then it pushes both errors out on the same line, but all other errors show correctly, like this
The postcode must be at least 5 characters,Sorry, the postcode must start with a letter.
The username field is required.
The address line 1 field is required.
Why is laravel pushing the min and regex rule messages out on the same line?

As described in the docs, validation rules should be expressed as a string, with different rules for a single input separated by a pipe |. The set of inputs to be validated should be an array, but not the rules themselves.
In your case, for the postcode input:
'postcode' => 'required|min:5|max:8|regex:/^[a-z]/i',

That means your $error is an array. if you want to list all error as new line, check if the error is also an array or is not an array.
#if(count($errors) > 0)
#foreach($errors->all() as $error)
#if(is_string($error))
<li>{{$error}}</li>
#else
#foreach( $error as $newBreakdown)
<li>{{$newBreakdown}}</li>
#endforeach
#endif
#endforeach
#endif

Related

Laravel array validation dont show error message

Firstly I can say that after search I dont find any solution about this. I do validation array like this post: laravel validation array
I need validate each size array position. I write this validation code:
// Fields validation
$request->validate([
'name' => 'required|max:150',
'theySay' => 'nullable|array',
'theySay.*' => 'string|max:1000',
'theyDontSay' => 'nullable|array',
'theyDontSay.*' => 'string|max:1000',
]
Where theySay and theyDontSay are both array of strings. In migration I have both fields (text) like strings of 1000 characters.
$table->string('text', 1000);
And validation works correctly. I mean, if put a text greater than 1000 chars I cannot save but..dont show any error message.
I want the error message to be shown in the input just like the rest of the fields.
What am I doing wrong?
Best regards
'YOUR_FIELD' => '...|...|max:1000| ...'
Look at the Laravel validation docs for more information
Please put below code in your blade file for show any error message.
#if ($errors->any())
<div class="alert alert-danger">
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif

Validation errors message on array

Quoting laravel documentation:
Likewise, you may use the * character when specifying your validation messages in your language files, making it a breeze to use a single validation message for array based fields:
'custom' => ['person.*.email' => ['unique' => 'Each person must have a unique e-mail address']]
It seems it does not work. I have a validation message:
'infos.*.*.*' => ['required' => 'My text']
Then I have some inputs in my view:
<input type="text" name="infos[1234][0][name]">
<input type="text" name="infos[1234][1][name]">
<input type="text" name="infos[5678][0][name]">
And in my controller I validate the input:
$this->validate($request, [
'infos.*.*.*' => 'required'
]);
And in view I have a error displayer:
#if (count($errors) > 0)
<strong>Oops. Errors:</strong>
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
#endif
And if I leave all input empty I got:
My text
My text
My text
My text
My text
etc.
What's wrong with my code? Reading Laravel documentation I though it should have worked (I mean: it should have been displayed only once). Did I misunderstood something?
This is working as intended. Since you're passing multiple inputs in an array, the validation throws an error for each item. Therefore 3 inputs with 2 causing errors and 1 passing would obviously pass error for 2 inputs. So in your case the multiple errors are due to multiple inputs failing validation.

Laravel form validation, why I don't have the $errors variable available on my view?

Taken from lrvl 5.1 documentation, I read:
using these lines in the controller:
$this->validate($request, [
'title' => 'required|unique:posts|max:255',
'author.name' => 'required',
'author.description' => 'required',
]);
If validation doesn't pass controller stops execution and redirect back to previous location.
This is happening correctly.
Then doc says:
"$errors variable will always be available in all of your views on every request"
And then suggests the following blade code:
#if (count($errors) > 0)
<div class="alert alert-danger">
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
But actually I'll get a ErrorException undefined variable errors....
What am I missing?
Thanks
I'll answer myself to this question,
just in case It was not clear the commented solution.
(Thanks to train_fox for the hint).
Just add 'web' middleware usage.
in your routing that is target in form action (get/post)
Example:
Route::group(['middleware' => 'web'],
function(){
Route::post('/edit' , 'My_Controller#edit');
});
Variable $errors the becomes available on view to be parsed.

required_without_all validator repeats error message over and over

I'm building a roster system as a side project and on one of the pages you can change the regular hours someone works.
On the page I have a checkbox for each day of the week, you can then go through and select the appropriate days that the person works.
They need to work at least one day and so at least one of the checkboxes needs to be checked when submitted.
To test this I am using the required_without_all rule of Laravel's validator.
It works perfectly, however if no boxes are checked it will redirect you back and spit out the same error message 7 times (as there are 7 checkboxes for each day of the week).
I am using custom error messages so this is why the error message is the same, but even if I didn't I wouldn't want a similar error message being repeated over and over.
This is what my validator looks like:
$validator = Validator::make($request->all(), [
'mondayCheckbox' => 'required_without_all:tuesdayCheckbox,wednesdayCheckbox,thursdayCheckbox,fridayCheckbox,saturdayCheckbox,sundayCheckbox',
'tuesdayCheckbox' => 'required_without_all:mondayCheckbox,wednesdayCheckbox,thursdayCheckbox,fridayCheckbox,saturdayCheckbox,sundayCheckbox',
'wednesdayCheckbox' => 'required_without_all:mondayCheckbox,tuesdayCheckbox,thursdayCheckbox,fridayCheckbox,saturdayCheckbox,sundayCheckbox',
'thursdayCheckbox' => 'required_without_all:mondayCheckbox,tuesdayCheckbox,wednesdayCheckbox,fridayCheckbox,saturdayCheckbox,sundayCheckbox',
'fridayCheckbox' => 'required_without_all:mondayCheckbox,tuesdayCheckbox,wednesdayCheckbox,thursdayCheckbox,saturdayCheckbox,sundayCheckbox',
'saturdayCheckbox' => 'required_without_all:mondayCheckbox,tuesdayCheckbox,wednesdayCheckbox,thursdayCheckbox,fridayCheckbox,sundayCheckbox',
'sundayCheckbox' => 'required_without_all:mondayCheckbox,tuesdayCheckbox,wednesdayCheckbox,thursdayCheckbox,fridayCheckbox,saturdayCheckbox',
'effective_from' => 'date',
], [
'mondayCheckbox.required_without_all' => 'Surely they are working at least one day!',
'tuesdayCheckbox.required_without_all' => 'Surely they are working at least one day!',
'wednesdayCheckbox.required_without_all' => 'Surely they are working at least one day!',
'thursdayCheckbox.required_without_all' => 'Surely they are working at least one day!',
'fridayCheckbox.required_without_all' => 'Surely they are working at least one day!',
'saturdayCheckbox.required_without_all' => 'Surely they are working at least one day!',
'sundayCheckbox.required_without_all' => 'Surely they are working at least one day!',
'effective_from.date' => 'You have provided an invalid date for when their hours are effective from!',
]);
if ($validator->fails())
{
return Redirect::back()
->withErrors($validator)
->withInput();
}
So if no boxes are checked on submission, the error Surely they are working at least one day! is shown 7 times.
I am displaying the errors on the page like this:
#if (count($errors) > 0)
<div class="alert alert-danger">
<p><b>There were some problems:</b></p>
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
Is there anyway to only get it to show once?
There are many ways to go around this. Since JS hacks are on the table too, we can also come in from the Blade end and do this (feel free to use your own favourite array manipulation functions):
<ul>
<li>
{{-- Show error message only once --}}
#if( $errors->has('mondayCheckbox') || $errors->has('tuesdayCheckbox') || $errors->has('wednesdayCheckbox') || $errors->has('thursdayCheckbox') || $errors->has('fridayCheckbox') || $errors->has('saturdayCheckbox') || $errors->has('sundayCheckbox') )
Surely they are working at least one day!
#endif
</li>
#foreach ($errors->all() as $error)
{{-- Show other errors not related to the checkboxes --}}
#unless($error == 'Surely they are working at least one day!')
<li>
{{ $error }}
</li>
#endunless
#endforeach
</ul>
The other way is to deal with the Illuminate\Contracts\Support\MessageBag in your validator with the After Validation Hook and clean things up there.
It is late but might help someone with similar problem.
Just apply the rule for a hypothetical field, say, weekdays like below.
$validator = Validator::make($request->all(), [
'weekdays' => 'required_without_all:mondayCheckbox,tuesdayCheckbox,wednesdayCheckbox,thursdayCheckbox,fridayCheckbox,saturdayCheckbox,sundayCheckbox',
'effective_from' => 'date',
], [
'required_without_all' => 'Surely they are working at least one day!',
'effective_from.date' => 'You have provided an invalid date for when their hours are effective from!',
]);
And put all the fields (mondayCheckbox.... sundayCheckbox) that you want this rule to be applied after required_without_all. And write the validation message for the rule only once.
You can use array_unique($array) function to remove duplicates from error messages.
Here is the code snippet
#if ($errors->any())
<div class="alert alert-danger">
<ul>
#foreach (array_unique($errors->all()) as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif

Displaying validation errors from an input array in Laravel

I am submitting an array of inputs to my controller like so:
<input id="box-1-nickname" name="box-nickname[]" class="form-control" type="text" placeholder="Required">
<input id="box-2-nickname" name="box-nickname[]" class="form-control" type="text" placeholder="Required">
I am doing some validation like this:
$validator = Validator::make(Input::all(), array(
'supplies-count' => 'required|in:0,1,2,3,4',
));
$arrayValidator = Validator::make(Input::all(), []);
$arrayValidator->each('box-nickname', ['required|min:1|max:60']);
if( $validator->fails() || $arrayValidator->fails() ) {
return Redirect::route('route-2')
->withErrors($arrayValidator)
->withInput();
}
The problem is when I try to check the errors like this it doesn't work:
if( $errors->has('box-1-nickname') ) { echo ' has-error'; }
Displaying input array errors in the view (L5.8 onwards)
To get the first validation error for an input array:
{{ $errors->first('input_array.*') }}
To check if there is an error within an input array:
#if($errors->has('input_array.*'))
<h1>There is an error in your input array</h1>
<ul>
#foreach($errors->get('input_array.*') as $errors)
#foreach($errors as $error)
<li>{{ $error }}</li>
#endforeach
#endforeach
</ul>
#endif
Other examples:
#error('input_array.*')
<div class="alert alert-danger">{{ $message }}</div>
#enderror
From 5.8^ documentation
Working with error messages
If you are validating an array form field, you may retrieve all of the messages for each of the array elements using the * character:
foreach ($errors->get('attachments.*') as $message) {
//
}
Hope it helps!
You've probably long found a solution, but for anyone else who stumbles across this:
The validator uses array dot notation of the field array keys. For example box-nickname[0] becomes box-nickname.0
Therefore if( $messages->has('box-nickname.0') ) { echo ' has-error'; } should give you your desired result. However, you will need to dynamically generate the array key since as you've said, you won't know how many box-nicknames are being applied. I use this in my form view:
#if(!is_null(Input::old('box-nickname')))
#foreach(Input::old('box-nickname') as $n => $box-nickname)
#include('box-nickname-create-form-partial')
#endforeach
#endif
Then create a partial view called "box-nickname-create-form-partial.blade.php" or whatever you want to call it with the form field, which might look something like this:
<div class="form-group {!! $errors->has('box-nickname.'.$n) ? ' has-error' : '' !!}">
<input name="box-nickname[{{$n}}]" class="form-control" type="text" placeholder="Required">
</div>
I hope that's helpful.
The errors are collected by name property, not id, and Laravel's default MessageBag variable is $messages, not $errors:
if( $messages->has('box-nickname') ) { echo ' has-error'; }
http://laravel.com/docs/4.2/validation#working-with-error-messages
$errors is correct, but you should be checking for box-nickname. As you can see you will run into the issue of not being able to identify what box is what because of the generic name. I think the easiest way to to give each input a unique name (eg. box-1, box-2)and do a for loop on the server side to retrieve inputs that start with box-.

Categories