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
Related
Event::factory(5)
->hasAttached(
Team::factory()->count($this->faker()->numberBetween(0, 60)),
[
'team_name' => $this->faker()->unique()->name,
'score' => $this->faker()->numberBetween(0, 50)
],
'participants'
)
->create([
'user_id' => $user,
'quiz_id' => $quiz
]);
The above snippet of code creates 5 events for said $user using said $quiz. It will have a random amount of participants which is a pivot table (Team and Event). On that pivot table there is a team_name and score column. Because teams can change their team name we want to know the team name at the time of participating and also the score in which they got for the event.
With the current code, because $this->faker()->numberBetween(0, 60), $this->faker()->unique()->name and $this->faker()->numberBetween(0, 50) are not evaluated within an iteration, all the pivot table data is the same.
How can I make this data different per pivot row?
TIA
Figured it out;
Event::factory(5)
->hasAttached(
Team::factory()->count($this->faker()->numberBetween(0, 60)),
function() {
return [
'team_name' => $this->faker()->unique()->name,
'score' => $this->faker()->numberBetween(0, 50)
];
},
'participants'
)
->create([
'user_id' => $user,
'quiz_id' => $quiz
]);
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,
Working on a Laravel application whereby am working on the backend validation of two dates. The 2 dates are mainly departureDate and returnDate respectively.
On the departure date am trying to validate it to be required, should be of type date and should be a date after today. On the return date I am also trying to implement a validation logic whereby return date should be 3 days or more after departure date but it should be less than 180 days after departure date.
Validate function
public function validateDates(Request $request){
//dd($request->all());
$now = new \DateTime();
$after_date = $now->parse($this->departureDate)->addDays(3);
$maxdays = $now->parse($this->departureDate)->addDays(180);
$validation = $this->validate($request, [
'departureDate' => 'required|date|after:now',
'returnDate' => 'required|date_format:"Y-m-d"|after:' . $after_date->toDateString().'|before:' . $maxdays->toDateString()
],
[
'departureDate.after' => 'Your departure date should be tomorrow or any date in the future',
'returnDate.after' => 'Your return date should be 3 or more days after the departure date',
'returnDate.before' => 'Your return date should be no more than 180 days from the departure date',
]
};
I think your logic is fine. You are, however, probably looking to use Carbon instead. It has the parse() method you are looking for. Also addDays() and toDateString().
So, on top of your file, add the following statement:
use Carbon\Carbon;
and then change your validateDate() method to this one:
public function validateDates(Request $request)
{
$after_date = Carbon::parse($this->departureDate)->addDays(3)->toDateString();
$max_days = Carbon::parse($this->departureDate)->addDays(180)->toDateString();
$validation = $this->validate($request,
[
'departureDate' => 'required|date|after:now',
'returnDate' => 'required|date_format:"Y-m-d"|after:' . $after_date . '|before:' . $max_days
],
[
'departureDate.after' => 'Your departure date should be tomorrow or any date in the future',
'returnDate.after' => 'Your return date should be 3 or more days after the departure date',
'returnDate.before' => 'Your return date should be no more than 180 days from the departure date',
]
);
};
I am assuming that you have your departureDate defined somewhere and hence you are using $this->departureDate, but if it's coming from your request instead, you should change that to $request->departureDate for example.
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
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'),
]);