I am not able to display the validation errors on a specific form/page when using $request->validate($rules);. Here is the controller code:
public function store(Request $request) {
$rules = [
'dummy-field' => 'required|string',
];
$params = $request->validate($rules);
// $this->validate($request, $rules); // Same result with this
dd($params);
}
In my view:
#if($errors->any())
<div class="alert alert-danger">
#foreach($errors->all() as $error)
<div>{{ $error }}</div>
#endforeach
</div>
#endif
When I submit the form (without the dummy-field) I'm properly redirected back to the previous page (If my form would pass the validation I should see the dd output), but the error messages are not displayed. I also tried dd($errors) and the ErrorBag is actually empty.
The weird thing is, using a manual Validator the error messages are properly displayed. Refactoring the controller to:
$rules = [
'dummy-field' => 'required|string',
];
$validator = Validator::make($request->all(), $rules);
if ($validator->fails()) {
return redirect()->back()->withErrors($validator);
}
dd($validator);
I see the error messages.
I really can't understand this behaviour. I'm using $request->validate() for other forms in my app and I don't have any trouble.
I'm using laravel 8.
Does someone have any idea why something like this could happen?
I finally found a solution. Posting it here in case it may help someone.
The problem lies in the cookie session driver
The browser has a maximum size for a cookie (around 4k I think, but it may vary). When using $request->validate(), the redirect will put into the session both the errors and the input. If the input is long enough (in my case I had some textarea with ~300 characters text), the cookie will exceed the maximum size and the browser will ignore it, so Laravel will not be able to retrieve the errors from the session.
I can't use the file driver because my application is distributed across multiple servers beyond a load balancer, so I resolved everything using the redis driver.
Related
How do I use validateWithBag90 in Laravel 9? I tried a lot of combinations and I'm getting a bit frustrated.
$validator = Validator::make($request->all(), [
'old' => 'required',
'new' => 'required|string|confirmed',
]);
if ($validator->fails()) {
return redirect()->back()->with('error', $validator);
}
I'm getting this error.
Serialization of 'Closure' is not allowed
Any ideas?
Manually Creating Validators
After determining whether the request validation failed, you may use
the withErrors method to flash the error messages to the session. When
using this method, the $errors variable will automatically be shared
with your views after redirection, allowing you to easily display them
back to the user. The withErrors method accepts a validator, a
MessageBag, or a PHP array.
Instead of:
// ...
->with('error', $validator); ❌
// ...
Use this:
// ...
if ($validator->fails()) {
return redirect()
->back()
->withErrors($validator) ✅
->withInput();
}
// ...
Addendum
Displaying The Validation Errors
An $errors variable is shared with all of your application's views
by the Illuminate\View\Middleware\ShareErrorsFromSession middleware,
which is provided by the web middleware group. When this middleware is
applied an $errors variable will always be available in your views,
allowing you to conveniently assume the $errors variable is always
defined and can be safely used. The $errors variable will be an
instance of Illuminate\Support\MessageBag.
<!-- /resources/views/post/create.blade.php -->
<h1>Create Post</h1>
#if ($errors->any())
<div class="alert alert-danger">
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
<!-- Create Post Form -->
I create validation using laravel form request file and I want to set session in laravel request file and send the session with validation error to blade view.. can I do that ?
Thanks :)
Using Laravels validation whether that be within the App\Http\Requests or in the controller itself using
$this->validate($request, [
'name' => 'required
]);
Will automatically return errors back to the view itself for you to display within the $errors variable.
If you're calling the Validator::make() method yourself and wish to check the errors manually and redirect. You can do this by using
$validator = Validator::make($request, [...]);
if($validator->fails()) {
return redirect()->back()->withErrors($validator->errors());
}
After validation I want to pass some extra data to view. However, I can't send it.
My controller is like,
public function test()
{
$validator = Validator::make(
request()->all(),
[ 'ziptest' => 'regex:/^([0-9]{3}-[0-9]{4})$/']
);
$errors = $validator->errors();
if($errors->any()) {
return back()
->withErrors($errors)
->withTitle('Data From Controller')
->withInput();
}
return 'success';
}
In my blade I want to check if the title is passed or not. So in my blade view I have
#if($errors->any())
#foreach($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
#endif
#if(isset($title))
<p>{{ $title }}</p>
#endif
However, the error portion is displaying properly. But not the title. Why is it not working?
I also tried sending the title in this way.
return back()->withErrors($errors)
->with('title','Data From Controller')
->withInput();
It is also not working.
I searched in the SO and found several similar questions regarding passing data from controller to view. However, my situation is a bit different.
In your example, you are redirecting back to the previous location. When you use with* for a redirect the information is flashed to the session, rather than made directly available to the view like it would be if you were returning a view instead.
For it to work with your example, you would have to check session('title') to get the flashed title from the redirect.
Your second approach is almost correct.
return back()->withErrors($errors)
->with([
'title' => 'Data From Controller'
])
->withInput();
note the array notation
use here array_merge method
$errors = $validator->errors();
if($errors->any()) {
$newErrors = array_merge($errors->toArray(),['title' => 'Data From Controller']);
return back()
->withErrors($newErrors)
->withInput();
}
Did you tried after validation hook but it will return data as in error bag
$validator->after(function ($validator) {
$validator->errors()->add('someField', 'Somedata');
});
And i'm wondering from where are you calling view because i saw your test() method do only validation part, with you're view you can pass data with it but with validation i think as in error bag you can send data to view.
Let me tell you my situation. I have made a simple library/module which I can popupulate in my controller. This way I can use one view file and have different results just by changing some of the $form fields(like text inputs, selects, etc). The example is below:
$form = new FormHelper('Webshop bewerken','shop/update',$errors);
$form->addHiddenInput('id',$id);
$form->addTextInput('name','Naam',$item->name);
$form->addTextInput('export','Uitvoer',$item->output_location);
$form->addTextInput('method','Methode',$item->method);
$form->addSidebar();
$form->generateForm();
//show the page
$this->layout->content = View::make('item')->with('form',$form);
The problem exist not within the form. This works fine until i need to validate. However the $errors is undefined so i cannot render the errors.
I have noticed that this variable is only available in the view and not in the controller.
This is fine if you have just a few blade.php files but not in my case(many many screens with generic information).
How can I access the $errors variable (output from the laravel validator) in a controller and not view?
Below is a validator code example i use:
//run the validator
$validator = Validator::make(Input::all(), $rules);
if ($validator->fails()) {
return Redirect::back()->withInput()->withErrors($validator);
} else {
//do something else(not relevant)
}
In your controller you may use:
$validator = Validator::make(Input::all(), $rules);
$errors = $validator->errors();
This will give you the same errors that you get in the view. To access a particular error you may use:
$error = $validator->errors('someFormFieldName')->first();
I'm using the validation rules in Laravel 4, which are very powerful. However, I wonder how one can distinguish between the different validations error that may occur. For example if I use the following rules:
$rules = array(
'email' => 'required|email|confirmed',
'email_confirmation' => 'required|email',
);
How can I tell what validation rule/rules that triggered the error for a certain field? Is there some way I can tell that the error was due to a missing email value, email wasn't a valid email address and/or the email couldn't be confirmed?
I quite new to laravel as I began working with it a week ago so I hope someone may shed some light on this.
The validation messages returned by the validation instance should hold the key to knowing what went wrong.
You can access the messages given by the validator object by using:
$messages = $validator->messages(); // Where $validator is your validator instance.
$messages = $messages->all()
That should give you an instance of a MessageBag object, that you can run through with a foreach loop:
foreach ($messages as $message) {
print $message;
}
And inside there, you should find your answer, i.e. there will be a message saying something like: "Email confirmation must match the 'email' field".
You can get error messages for a given attribute:
$errors = $validation->errors->get('email');
and then loop through the errors
foreach ($errors as $error) {
print $error;
}
or get all the error messages
$errors = $validation->errors->all();
then loop through the error messages
foreach ($errors as $error) {
print $error;
}
You can see more information about laravel validation here