Laravel 5.4 sometimes|required validation not raising on "null" input - php

I'm having a problem validating inputs that are only going to be present sometimes in the Request.
// Controller
public function update(Request $request, User $user)
{
$updateResult = $user->updateUser($request);
return dd($updateResult);
}
// User Model
protected $validation = [
'rules' => [
'email' => [
'sometimes',
'email',
'required',
],
'password' => [
'sometimes',
'min:6',
'required',
],
'first_name' => [
'sometimes',
'required',
],
'last_name' => [
'sometimes',
'required',
],
],
'messages' => [
'email.required' => 'An email is required.',
'email.email' => 'The email must be valid.',
'password.required' => 'A password is required.',
'password.min' => 'Your password must be at least six (6) characters long.',
'first_name.required' => 'Your first name is required.',
'last_name.required' => 'Your last name is required.',
],
];
public function updateUser(Request $request)
{
$validation = Validator::make($request->all(), [
$this->validation['rules'],
$this->validation['messages'],
]);
if ($validation->fails())
{
return $validation;
}
else
{
return "OK";
}
}
So in some update pages $request->all() is only going to have a subset of these fields. However, even a field is present, but the value is null, the required doesn't trigger.
[
'first_name' => null,
'last_name' => 'Davidson',
'job_title' => 'Tech Support',
]
The above request array will return "OK"... If I remove sometimes from the fields, then when a partial input request is sent, it fails saying the fields are required.
I am clearing missing something here, but from reading the docs I thought I'd configured this correctly:
In some situations, you may wish to run validation checks against a
field only if that field is present in the input array. To quickly
accomplish this, add the sometimes rule to your rule list:
$v = Validator::make($data, [
'email' => 'sometimes|required|email', ]);

The problem you are facing is simply due to an error in your call to the validator. The second parameter is not a multidimensional array as you passed. The rules array and the messages array are separate parameters.
$validation = Validator::make($request->all(), [
$this->validation['rules'],
$this->validation['messages'],
]);
Should be replaced by
$validation = Validator::make($request->all(),
$this->validation['rules'], $this->validation['messages']);

In Laravel 5.4 empty strings are converted to Null by the ConvertEmptyStringsToNull middleware... that might cause you some issues...
You should add nullable to all your optional validations...
Hope this helps

'first_name' => [
'sometimes',
'required',
],
Will never work as expected. Sometimes indicates: if something comes, what is the next rule? In this case 'required'. Required what? Change this to:
'first_name' => [
'sometimes',
'required',
'min:1',
],
The null value will still be a null value if no input is given and won't fail. If you want to keep the value of the field in the table for updates, populate the input in the form with it's respected values.
The null value was send as '' and got nulled by the ConvertEmptyStringsToNull::class in the app\Http\kernel.php middleware.

Related

How can I set custom validation error messages from a controller, in Laravel 8?

I am working on a registration form with Laravel 8 and Sanctum.
I have this piece of code in the AuthController to validate the form fields:
public function register(Request $request) {
$fields = $request->validate([
'first_name' => 'required|string,',
'last_name' => 'required|string',
'email' => 'required|string|unique:users,email',
'password' => 'required|string|confirmed',
'accept' => 'accepted',
]);
// More code here
}
I want to display more user-friendly validation error messages.
Rather than changing the validation.php file (resources\lang\en\validation.php), I want to change the set them for the registration form only, in the method above.
The problem
As someone that has used Codeigniter for a long time, I had, in Codeigniter, the posibility to do just that:
$this->form_validation->set_rules('first_name', 'First name', 'required', array('required' => 'The "First name" field is required'));
I was unable to do something similar in Laravel 8.
How do I get the desired result in Laravel 8?
Maybe this can work for ya.
$rules = [
'first_name' => 'required|string,',
'last_name' => 'required|string',
'email' => 'required|string|unique:users,email',
'password' => 'required|string|confirmed',
'accept' => 'accepted'
];
$customMessages = [
'required' => 'The :attribute field is required.'
];
$this->validate($request, $rules, $customMessages);
Also check out the laravel customizing error messages documentation.
The validate function excepts 3 parameters. A) request, B) the rules, C) Custome Messages.
$this->validate($request, $rules, $customMessages); It means define your custom Message Array by key value. Key is the rulename like require. For example:
[
'required' => 'The :attribute is really,really, really required if you use Login!'
'email.required' => 'Without email you dont come in ;-)'
]

How to redirect back if validate method fails with Laravel

I am using Laravel 6.
I created a form to insert a meeting and I created a validate method in the controller to check if the data inserted in the db are correct.
Unfortunately when the validate method fails the default redirect back deletes every field that has been compiled by the user.
I tried many times but I am unable to understand how to do in case of failure a redirect back with the previous values filled in by the user.
Controller:
{
$this->validate($request, [
'participants' => [ 'required', new CheckParticipant() ],
'description' => 'required',
'room' => [ 'required', new CheckRoom() ],
'date_meeting' => [ 'required', new CheckDateTime() ],
'start' => [ 'required', new CheckTime() ],
'end' => 'required',
]);
$meeting = new Meeting();
$participants = request('participants');
$meeting->id_participants = implode(';', $participants);
$meeting->description = request('description');
$meeting->id_room = request('room');
$meeting->date = request('date_meeting');
$meeting->start_hour = request('start');
$meeting->end_hour = request('end');
$meeting->save();
$message_correct = "The meeting has been correctly inserted!";
return redirect()->route('home')->with('success', $message_correct);
}
Finally if the user filled in for example the name of a participant to the meeting but the validate method fails I would like that the participant appears already selected in the dropdown menu after the default redirect back.
Is someone able to help me?
In your view, you can use the old function to retrieve data flashed from the previous request.
Instead of calling $this->validate try this:
$validator = Validator::make($request->all(), [
'participants' => [ 'required', new CheckParticipant() ],
'description' => 'required',
'room' => [ 'required', new CheckRoom() ],
'date_meeting' => [ 'required', new CheckDateTime() ],
'start' => [ 'required', new CheckTime() ],
'end' => 'required',
]);
if($validator->fails()) {
return redirect('your/url')
->withErrors($validator)
->withInput();
}
Then, in your view you can access the old inputs with old('yourValue').

Ignore validation rules if input value is empty ("")

I have a form to create a conference and I have some validation rules like below. For example the city is not required but should be a string. The issue is that when the user click in the "Store" button without fill the non required fields it appears the validation errors like:
The city must be a string.
Do you know how to solve that issue? If the value of the form field is "" ignore the rules?
public function store(Request $request)
{
$this->validate($request, [
'name' => 'required|string',
'categories' => 'array|between:1,3',
'city' => 'string',
'zip_code' => 'string',
]);
...
}
you can use nullable if anyone field is non requied field.below you can see the code...
public function store(Request $request)
{
$this->validate($request, [
'name' => 'required|string',
'categories' => 'nullable|array|between:1,3',
'city' => 'nullable|string',
'zip_code' => 'nullable|string',
]);
...
}

How can I check i 2 fields of a form have the same content using a rule array of laravelcollective/html validator?

I am pretty new in Laravel and I have the following problem.
I have this method that handle the submit of a form:
public function store(Request $request) {
Log::info('store() START');
$data = Input::all();
Log::info('INSERTED DATA: '.implode("|", $data));
$rules = array(
'name' => 'required',
'surname' => 'required',
'login' => 'required',
'email' => 'required|email',
'emailConfirm' => 'required|email',
'pass' => 'required',
'passlConfirm' => 'required',
'g-recaptcha-response' => 'required|captcha',
);
$validator = Validator::make($data, $rules);
if ($validator->fails()){
return Redirect::to('/registration')->withInput()->withErrors($validator);
}
else{
// Do your stuff.
}
}
As you can see it contains a $rules array containing the validation rules.
It works pretty fine but I want also perform the following 2 checks:
The email field have to contains the same text than the emailConfirm field.
The pass field have to contains the same text than the passConfirm field.
Can I implement this kind of check into the $rules array?
Actually Laravel comes with the validation rule called confirmed. You will need to change your fields to email_confirmation and pass_confirmation and add confirmed rule to email and pass fields.
As answered by #Mariusz, Laravel come up with value comparison rule as confirmed rule. To acheive your output you should write,
$rules = array(
'name' => 'required',
'surname' => 'required',
'login' => 'required',
'email' => 'required|confirmed|email',
'pass' => 'required|confirmed',
'g-recaptcha-response' => 'required|captcha',
);
As you have mentioned, you are using laravelcollective/html, then you have to also add following code to generate confirmation fields
echo Form::email("email_confirmation",null, $attributes = []);
echo Form::password("pass_confirmation",null, $attributes = []);

Laravel 5.2 validation check if value is not equal to a variable

In my instance one user is inviting another I would like to check if the user they are inviting is not themselves.
Thus I have two variables incomming email and user->email
$this->validate($request, [
'email' => 'required|email',
]);
How can I add that validation rule to the validation call?
You can use not_in, which allows you to specify a list of values to reject:
$this->validate($request, [
'email' => 'required|email|not_in:'.$user->email,
]);
You can use different:field according to the laravel Document
For instanse in your requests validation:
public function rules()
{
return [
'from' => 'required',
'to' => 'required|different:from',
'action' => 'required',
'access' => 'required'
];
}
These two from and to should be different(not same).
As #Vlad Barseghyan mentioned in the accepted answer:
The case is that if from will be from='3' and to=3, they will considered as different.
That's because of how the different validation rule compares the given fields. It uses strict comparison which leads to unexpected behavior in some cases when dealing with integers.
The not_in rule uses loose comparison and it can be used to accomplish the same behavior of different rule.
public function rules()
{
return [
'from' => 'required',
'to' => 'required|not_in:' . $this->from,
'action' => 'required',
'access' => 'required'
];
}
public function messages()
{
return [
'to.not_in' =>
'to and from should be different.'
];
}

Categories