Laravel 5 validation append to rule - laravel

I'm using Laravel 5.4 and I have 2 date fields. The first is required and the second is optional.
I'm having problems with the validation when the second date field is empty.
I understand why but only want to run the before_or_equal rule if the second date is not empty
$this->validate($request, [
'start_date' => 'required|date|before_or_equal:end_date',
'end_date' => 'nullable|bail|date|after_or_equal:start_date',
]);
How can I update my code ignore the rule if the date field is empty?
I did think about this
if($request->has('end_date')) {
//do something
}
The only other option is to create a custom validation rule and compare the dates

No need to put both condition remove |before_or_equal:end_date from start_date. Only after_or_equal:start_date would work
Use required_with:foo,bar,...
Try like this
$this->validate($request, [
'start_date' => 'required|date',
'end_date' => 'required_with:start_date|nullable|bail|date|after_or_equal:start_date',
]);

I would do it like this:
$rules = [
'start_date' => 'required|date|before_or_equal:end_date',
];
if ($request->get('end_date') != '') {
$rules['end_date'] = 'required|date|after_or_equal:start_date';
}
$this->validate($request, $rules);

Related

The unique Rule validation is not applied

I am using laravel 9.
And I have this very simple validation rule (form request validation):
public function rules()
{
return [
'first_name' => 'required|max:50',
'last_name' => 'required|max:50',
'email' => [
'email',
Rule::unique('unknown_table')->where(function ($query) {
return $query->where('library_id', $this->library->id);
})
],
.......
What I do not understand is why my post is working with this table name "unknown_table", because this table really does not exist. I expected an exception but nothing happens !
Is this rule correctly written ?
I have understood my error. The "email" validation was twice in the rule array ! And it was the last one which was used of course.

Laravel validations

I want to validate my backend code with the following data.I passed date as $request->get('date_from'),$request->get('date_to') and time as $request->get('time_from'), $request->get('time_to') from my angular frontend and I convert date time as follows.
$dateTime_from=date('Y-m-d',strtotime($request->get('date_from'))).' '.$request->get('time_from');
$dateTime_to=date('Y-m-d',strtotime($request->get('date_to'))).' '.$request->get('time_to');
Now I want to validate DateTime with laravel backend validations. dateTime_from should be less than dateTime_to.How can write down that code inside validator?
$this->validate($request, [
'vehicle_id'=>'required',
'time_to'=>'required',
'event_id'=>'required',
]);
You can use the after validation rule.
$this->validate($request, [
'vehicle_id' => 'required',
'date_to' => 'required|after:date_from',
'event_id' => 'required'
]);
https://laravel.com/docs/5.8/validation#rule-after
you can use the after rule like follows
'date_to' => 'required|date|after:date_from'
Instead of passing a date string to be evaluated by strtotime, you may specify another field to compare against the date:
Also, you have rule-before as well
EDIT
I think after rule takes the time into consideration as well, but not sure.
And you have really complex validation to do, better write a custom rule class or a closure to handle it for you
'date_to' => [ 'required',
'date',
function ($attribute, $value, $fail) {
if (strtotime($value) <= strtotime($request->date_from) {
$fail(':attribute needs to be higher than date_from!'); // or whatever mesage ou need to send
}
]

Laravel - exclude current email from unique validation

I am trying to use unique on an email address in Laravel 5.5 validation like this..
$rules = [
'email' => 'email|unique:users,email,
];
This is working and is checking the 'users' table in the 'email' column
But if the email address is the same as the currently saved one then this also fails validation.
Is there a way I can add an exception rule to the validation to ignore $user-email?
The unique rule takes a third parameter: a record to ignore, see "Forcing A Unique Rule To Ignore A Given ID".
Pass in the ID of the record you do not wish to be included in the unique test, e.g:
$rules = [
'email' => 'email|unique:users,email,' . $user->id
];
THIS IS AN EASY SOLUTION
Just add $this->route('id') as the third parameter
if your route was defined like this:
Route::put('{company}', 'CompanyController#update')
->name('update');
then your parameter name is "company"
So in your FormRequest:
public function rules()
{
$rules = [
'url' => [
'required',
'url',
'unique:companies,url,'.$this->route('company') ?? 0
],
];
// dd($rules); << check yourself
return $rules;
}
This FormRequest works the same for insert or update.
this line will instruct to ignore "0" in case of insert
$this->route('company') ?? 0

Validating Matching Strings

When I use the Validation feature in Laravel, how can I add a pre-defined strings that are allowed in an Input?
For example, let's say I want the Input to contain only one of the following: foo,bar,baz, how can I do that?
$validator = Validator::make($credentials, [
'profile' => 'required|max:255', // Here I want Predefined allowed values for it
]);
Best to use the 'in' validation rule like this:
$validator = Validator::make($credentials, [
'profile' => ["required" , "max:255", "in:foo,bar,baz"]
]);
It is recommended in Laravel docs to put the validation rules in an array when they get bigger and I thought 3 rules were sufficient. I think it makes it for a more readable content but you do not have to. I added the regex portion below and I have it works. I am not that great with regexing stuff. Let me know.
$validator = Validator::make($credentials, [
'profile' => ["required" , "max:255", "regex:(foo|bar|baz)"]
]);
Works for me in Laravel 9:
use Illuminate\Validation\Rule;
 
Validator::make($data, [
'toppings' => [
'required',
Rule::notIn(['sprinkles', 'cherries']),
],
]);
Docs: https://laravel.com/docs/9.x/validation#rule-not-in
For the opposite you could use Rule::in(['foo', 'bar', 'baz'])

Check user's age with laravel validation rules

How can I check the age of a user upon registration? I want to set the minimum age to be 13 years old. I ask for the user's date of birth and when I validate the other credentials, I want to check that they are in fact 13+.
An excerpt from my User model looks like this:
$rules = [
'name' => 'required|alpha|min:1',
'email' => 'required|email|unique:users',
'dob' => 'required|date'
];
How can I check that the date entered is 13 years ago or more?
I have seen that I can use the before:yyy-mm-dd rule from the Laravel Docs, like so:
$rules = [
'name' => 'required|alpha|min:1',
'email' => 'required|email|unique:users',
'dob' => 'required|date|before:2001-04-15'
];
How do I calculate the value?
How do I use that value within the rules?
A simple way to check that the date is greater(older) than N years is to set the before rule to minus N years.
$rules = [
'dob' => 'required|date|before:-13 years',
]
You can use Carbon which comes with laravel
$dt = new Carbon\Carbon();
$before = $dt->subYears(13)->format('Y-m-d');
$rules = [
...
'dob' => 'required|date|before:' . $before
];
RMcLeod answer is OK, but I'd suggest you extracting this as a custom rule:
Validator::extend('olderThan', function($attribute, $value, $parameters)
{
$minAge = ( ! empty($parameters)) ? (int) $parameters[0] : 13;
return (new DateTime)->diff(new DateTime($value))->y >= $minAge;
// or the same using Carbon:
// return Carbon\Carbon::now()->diff(new Carbon\Carbon($value))->y >= $minAge;
});
This way you can use the rule for any age you like:
$rules = ['dob' => 'olderThan']; // checks for 13 years as a default age
$rules = ['dob' => 'olderThan:15']; // checks for 15 years etc
This is a bit old, but I want to share the way I do it.
public function rules()
{
return
[
...
'age' => 'required|date|before_or_equal:'.\Carbon\Carbon::now()->subYears(18)->format('Y-m-d'),
...
];
}
Using before is nice but it's a bit ugly for the end user, because if today it's his birthday, he won't be able to pass. With before_or_equal you get the perfect behaviour. A way to improve this would be checking the timezone with Carbon if you target a worldwide audience.
I have Implement This & Successfully Work
You Can Use
before:'.now()->subYears(18)->toDateString()
$validator = Validator::make($request->all(), [
'birthdate' => 'required|date|before:'.now()->subYears(18)->toDateString(),
], [
'birthdate.before' => trans('18 year validation'),
]);

Resources