Check user's age with laravel validation rules - validation

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'),
]);

Related

How to validate date of birth and minimum age

I have a date of birth , and I will wish to do 2 things:
1) When, the use enters a date of birth, tha date should be coherent...
For example, if I enter, 2030-10-10, I must have an error message because the date is not coherent. Idem, if I enter 1947-10-10.
2) Is it possible to set the minimum age to be 18 years old?
In my model I have this:
protected $fillable = ['name_mark', 'dateofbirth', 'date_register'];
protected $dates = ['dateofbirth', 'date_register'];
In my Controller I have this:
public function store(Request $request)
{
$request->validate([
'name_mark' => 'required|min:3',
'dateofbirth' => 'required|date',
'date_register' => 'required|date'
]);
Mark::create($request->all());
flashy('Valider');
return redirect()->route('marks.index')
->with('success', 'save');
}
I am yet novice, I thank you for your help and explanation.
You can try using:
before:'.\Carbon\Carbon::now().'|before:18 years ago|
Or:
before:'.Carbon::now().'|before:'.Carbon::now()->subYears(13).'
This works for me, hope it will help you
You can try this:
'dateofbirth' => 'required|date|after:' . $date,

issue with validation two columns at once

I have an issue with validation by two columns in laravel
I have table work_hours with user_id and date and hours and I have more than one user so I need to give user opportunities to add his hours but only once for a specific date for example
Add 8 hours on 28-03-2018 for user_id = 9, but only once so If user try add once again Add 8 hours on 28-03-2018 for user_id = 9 He has information this date has already taken.
I wrote validation:
$validator = Validator::make($request->all(), [
'date' => 'unique:work_hours',
'name_of_hours' => 'required',
]);
but this work that if somebody of users Add 8 hours on 28-03-2018 for user_id = 9, user_id=10 or another can't add hours on this same date.
So, I need validation for two columns at once, user_id and date but I don't know how to do it.
This sounds like a good case for closures.
$validator = Validator::make($request->all(), [
'date' => function ($attribute, $value, $fail) {
// check the table for the date and current user
$date = DB::table('work_hours')->where([
['date', $value],
['user_id', Auth::user()->id]
])->first();
// if it exists then you fail
if ($date) $fail($attribute.' is invalid.');
},
'name_of_hours' => 'required',
]);
You can review the documentation here: https://laravel.com/docs/5.8/validation#using-closures

Laravel 5 validation append to rule

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);

Laravel 5 Validate Birthdate From Select Fields

I have a registration form with 3 select fields (month, day, year) which I want to grab, convert to proper date format, and validate. So, below are the 3 select boxes.
<div class="birthday_selects">
<select name="birthday_month">
....
</select>
<select name="birthday_day">
....
</select>
<select name="birthday_year">
....
</select>
</div>
I've read that I can use the following, but I get the error "...Http\Input not found..."
$birthday = Input::get('birthday_month')."-".Input::get('birthday_day')."-".Input::get('birthday_year')'
Okay, I can dd($birthday) and it comes out in the m-d-y as I've concatenated there. Now, I'm trying to validate that date against a prior date (to see if user is >13 years old). I'm using the following, but no luck.
public function postSignup(Request $request)
{
$birthdate = Input::get('birthday-month')."-".Input::get('birthday-day')."-".Input::get('birthday-year');
$this->validate($request, [
$birthdate => 'required',
]);
dd($birthdate);
}
When just having it be required, it doesn't work.
Your help is appreciated. Thanks!
It's not working because you're doing it wrong. What is wrong with it is the rule.
The rule key must be present in the form field's name.
For your answer, let's assume the $birthday will be 'jul-15-1992'. and you're going to put that variable inside the rule as a key. So, that's not valid because the field will never be present in the form field.
public function formPost(Request $request)
{
$rule = [
'birth_year' => 'required|numeric',
'birth_day' => 'required|numeric',
'birth_month' => 'required|numeric', // may be a string
];
$this->validate($request, $rule);
// check if the day is valid for the month manually.
// then form the DOB now.
}
Create Carbon date and add new [birth_day] input:
$all = $request->all();
$year = $all['birthday_year'];
$month = $all['birthday_month'];
$day = $all['birthday_day'];
// Create Carbon date
$date = Carbon::createFromFormat('Y-m-d', $year.'-'.$month.'-'.$day);
//add new [birth_day] input
$request->request->add(['birth_day' => $date->format('Y-m-d')]);
$validatedData = $request->validate([
'first_name' => 'required|string|max:255',
'last_name' => 'required|string|max:255',
'email' => 'required|string|email|max:255',
'password' => 'required|string',
'birth_day' => 'required|date_format:Y-m-d|before:today',// validate birth day
]);
Hope this will help you

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'])

Resources