Does Laravel validation rule default to sometimes? - laravel

If you create a validation rule in Laravel, but leave out |required and just use, say the email rule. What does it default to?
For example
$request->validate([
'email' => 'email'
]);
Are these validation rules equal?
$request->validate([
'email' => 'sometimes|email'
]);
// vs
$request->validate([
'email' => 'email'
]);
Apologies if this has been answered before. I tried my very best to search for similar questions, but I may have used the wrong words (not sure how to phrase this for a Google/Stack Overflow search).

$request->validate([
'email' => 'email'
]);
This will always validate the email key, even if empty, to be a valid email format.
$request->validate([
'email' => 'sometimes|email'
]);
This will only validate the email key if the key is present in $request->all().
So the difference is that with sometimes you'll only validate it if the $request object contains it, whilst otherwise it would always validate against the key.
If I could simplify it, I would say sometimes means, only apply the rest of the validation rules if the field shows up in the request. Imagine sometimes is like an if statement that checks if the field is present in the request/input before applying any of the rules.
It can be a tedious thing to wrap ones head around, but here is some examples:
input: []
rules: ['email' => 'sometimes|email']
result: pass, the request is empty so sometimes won't apply any of the rules
input: ['email' => '1']
rules: ['email' => 'sometimes|email']
result: fail, the field is present though invalid email so the email rule fails!
input: []
rules: ['email' => 'email']
result: fail, the request is empty so email is invalid!

I personally have never used the sometimes rule once. According to the docs:
https://laravel.com/docs/7.x/validation#conditionally-adding-rules
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
If I understand correctly, this largely depends on your frontend implementation. If you are using regular html <form> elements where you have an input with name="email", it will send a key named email as soon as you submit the form.
So in order to NOT send such key, you have to remove it from the form, or manually make a HTTP request (so disregarding any HTML form) such that you can decide your own input fields.

Related

Validate a field using another field

I have a dynamic phone number validation rule, and I need 2 values for it: number and country.
The library I'm using to validate the phone number is brick/phonenumber which can include the country code to parse it accurately.
So, my current working approach looks like this:
$request->validate([
'country' => ['required', 'max:2'],
]);
$request->validate([
'number' => ['required', new PhoneNumberValidator($request->input('country')],
]);
Because when I put it like this:
$request->validate([
'country' => ['required', 'max:2'],
'number' => ['required', new PhoneNumberValidator($request->input('country'))],
]);
The number validation runs even if the country is not valid. So I'd like to know if there's a way to have all the validations in one validate() call, so, having the country value validated before calling the number rule (I tried with bail but that stops the validations for 1 attribute, not the rest of attributes in the queue).
You can create a custom rule and validate both inputs at the same time.
You may also want to look at the various validation rules. You might find something helpful.

How to validate inputs from GET method? laravel

How can I validate my inputs from a GET method?
Example URL: localhost:8000?salary=2000&name=sample&description=vowewljfodigjfdglfd
In the URL I have 3 inputs and I want to validate:
Salary - should accept only numeric
Name - should accept only alphabetic
Description - should accept with max:1000
Somebody knows how to do this?
The Laravel validator doesn't care where the data came from. You can manually create a validator and pass it the query string data.
$validator = Validator::make($request->query(), [
'salary' => 'numeric',
'name' => 'alpha_num',
'description' => 'max:1000',
]);
if ($validator->fails()) {
// show an error
}
Side note: As someone with a hyphenated last name, I implore you not to treat name as alphanumeric. See Falsehoods Programmers Believe About Names.

Laravel: Validate input only if available in DOM

I created a form with the following fields:
Name
Email
Country
City
Address
If the user selects a country that has states (ex. United States) then the form transforms to:
Name
Email
Country
State
City
Address
To validate this I created a separate form request like so:
public function rules()
{
return [
'name' => 'required|max:255',
'email' => 'required|email,
'country_id' => 'required|integer',
'state_id' => 'nullable|integer',
'city_id' => 'required|integer',
'address' => 'required',
];
}
The problem is that if I leave it like that, then if I don't select a state it will pass validation.
If i make it:
'state_id' => 'sometimes|nullable|integer',
Then again it passes validation.
If I make it:
'state_id' => 'required|nullable|integer',
It will not pass validation, but then again it will throw a validation error if there is no state field in the form.
I read a lot of articles about this but nothing seems to solve it for me.
PS1: I want to solve this in the form request, not in the controller. I assume that an
if($request->has('states')){...}
can help, but then again, i would like to keep everything tidy in the form request.
PS2: I am using VueJS and Axios to add/remove states from the form. The whole form is actually a Vue component.
Any clues?
Thank you in advance!
You can conditionally add rules via the sometimes method on Validator.
$v->sometimes('state_id', 'required|integer', function ($input) {
return in_array($input->countries, [1,2,3,4...]
});
You could use the required_with line of parameters, but because the validation is based on the value of the input instead of just the presence, the custom validation rule is probably your best bet.
Per https://laravel.com/docs/5.7/validation#conditionally-adding-rules

Laravel form request validation

Is there any way to get original data in request?
I mean, in my case I want to validate updating user's in the form. I want the email to be unique on emails in database except on the email that user wrote to the form.
Laravel already has a validation rule for this, you can add an id of the user to ignore to your unique validator.
'email' => [
'required',
Rule::unique('users')->ignore($currentUser->id),
]
I used something like this:
'email' => ['sometimes', 'email', 'unique:users,email,'.$user->getKey().','.$user->getKeyName().',deleted_at,NULL', 'string'],
Not sure if it is the best solution but works. I kind of do not like it because the $user is based on hidden input from the request.
You can do it liks this:
'email' => 'unique:users,email,'.$user->id
The user id will allow you to keep updating the record but maintain the unique constraint on email. You don't need a hidden input field for $user->id btw.

Laravel 5.3 Validation Fails when Variables are Null

Since upgrading laravel from 5.1 to 5.3, I've got couple of odd issues with Validation.
When I post a data like this:
firstName null
And the validation rules are like this:
$validator = Validator::make($postData, [
'firstName' => 'string|max:255',
'lastName' => 'string|max:255'
]);
The above fails with the messages something like "The XYZ must be a string.". What I don't understand is:
Why is the validation failing when it is not set as required?
Meaning, it should ignore it and not throw an error if the value is
empty, right?
Why does the validation fail if the value is set as null?
Why does the validation fail when the parameter is not sent at all?
(like the lastName which is not posted at all)
Has something changed in Laravel 5.3 validations?
Add nullable rule:
'firstName' => 'string|max:255|nullable',
'lastName' => 'string|max:255|nullable'
The field under validation may be null. This is particularly useful when validating primitive such as strings and integers that can contain null values.
When you want something to be required but the value itself can be empty, like an empty string.
Validator::make($postData, [
'firstName' => 'present|string|max:255|nullable',
'lastName' => 'present|string|max:255|nullable'
]);
Useful in scenarios like "notes", which can be emptied by removing the input field from all its text and hit save.

Resources