Laravel validation difference between 2 dates - php

I need to check some special validation in my action store
public function store(Request $request) {
$this->validate($request, [
'practice'=>'required|max:100',
'project'=>'required',
'work_place'=>'required',
'telephone_1'=>'required',
'date_recurring_for_beginning' => 'required|date',
'date_recurring_for_end' => 'required|date|after_or_equal:date_recurring_for_beginning',
]);
RequestCollaborator::create($request->all());
return redirect()->route('requestsCollaborator.index')
->with('flash_message',
trans('request.request_created'));
}
I have to validate if the difference between date_recurring_for_beginning and date_recurring_for_end is 3 months?
there is any solution for doing this or I have to create a custom validation?

You can use Validator::extend() and can create your custom validation rule. Like
Validator::extend('valid_date_range', function ($attribute, $value, $parameters, $validator) {
$dateBeginning = \Carbon::createFromFormat('Y-m-d', $parameters[0]); // do confirm the date format.
$dateEnd = \Carbon::createFromFormat('Y-m-d', $value);
return $dateBeginning->diffInMonths($dateEnd) == $parameters[1];
});
You can use this like:
'date_recurring_for_end' => 'required|date|valid_date_range:date_recurring_for_beginning,3'
For more details about the custom validation. Please follow the documentation.
https://laravel.com/docs/5.8/validation

Create a custom validation rule within your app/Providers/AppServiceProvider:
public function boot()
{
Validator::extend('date_difference', function ($attribute, $value, $parameters, $validator) {
$firstDate = Carbon::parse($parameters[0]);
$secondDate = Carbon::parse($parameters[1]);
$minDifference = (int)$parameters[2];
if($firstDate->diffInMonths($secondDate) < $minDifference)
return false;
return true;
});
}
To use this rule:
$this->validate([
'some_field' => 'date_difference:date_one,date_two,3',
]);
Hope it helps.

Related

Livewire extended validation with dynamic replaced message

Adding a custom video length validaiton rule but the :max_duration is never replaced in the error message addReplacer method is never called. Is there a livewire way of doing this?
Validator::extend('video_length', function ($attribute, $value, $parameters, $validator) {
$max_seconds = $parameters[0];
// Replace dynamic variable
$validator->addReplacer('video_length_duration', function ($message, $attribute, $rule, $parameters) use ($max_seconds) {
return trim(str_replace(':max_duration', gmdate("H:i:s", $max_seconds), $message));
});
return false;
}, 'Video duration must be less then :max_duration');
$this->validate([
'file' => 'required|file|max:102400|video_length:86400',
]);

Birthday Date range validation issue in laravel

Hi I'm trying to validate my date of birth field validation
I need the age range has to be 18-45
I tried the following rule, but it's not working properly.
'date_of_birth_tcp2'=>'required|date|before:18 years|after:45 years'
You can achieve this using custom validation or as mentioned in comment.
'date_of_birth_tcp2'=>['required','date', function ($attribute, $value, $fail) {
$age=Carbon::parse($value)->diff(Carbon::now())->y;
//$age=Carbon::createFromFormat('d/m/Y',$value)->diff(Carbon::now())->y;
if($age<18||$age>45){
$fail('The '.$attribute.' is invalid.');
}
},]
Create a custom validation rule within your app/Providers/AppServiceProvider:
public function boot() {
Validator::extend('valid_date_range', function ($attribute, $value, $parameter, $validator) {
$dob = Carbon::parse($value)->diff(Carbon::now())->y;
if($dob < 18 || $dob > 45) {
return $fail('The given '.$attribute.' is invalid.');
}
});
}
To use this rule:
$this->validate([
'date_of_birth_tcp2' => 'valid_date_range:date_of_birth,3',
]);

How to create custom validation rule for dependent input fields in laravel

In my input form, I have two fields; momentFrom & momentTo. I need to put a validation which gives error message if any of the following criteria fails.
momentFrom is greater than or equal to momentTo.
momentFrom is less than now.
My code for storing the data:
public function store(Request $request, Requisition $requisitionObj) {
$momentFrom = strtotime($request->txtTravelDate . " " . $request->txtTimeFrom);
$momentTo = strtotime($request->txtTravelDate . " " . $request->txtTimeTo);
$timeValidation = $requisitionObj->validateTiming($momentFrom, $momentTo);
if ($timeValidation['error']) {
echo 'ERROR: ' . $timeValidation['message'];
return view('requisitions.create');
} else {
/* store form data into requisition object */
$requisitionObj->travel_date = $request->txtTravelDate;
$requisitionObj->moment_from = $momentFrom;
$requisitionObj->moment_to = $momentTo;
$requisitionObj->save();
return redirect()->route('requisitions.index');
}
}
I have seen laravel custom validation rules where only one field can be validated at a time. But in my scenario I need to check both fields at a time depending on each other. How can I achieve this?
Thanks for any help in advance!
Creating new Rule Class
You can create your custom rule with the artisan command: php artisan make:rule YourRuleNamethis will create a new Rule Class file into the Rules folder.
By default the created file contains a constructor, a passes method and a message method.
Rules Logic
If you have some complicated rules where you need the request or some models, you can pass them via the constructor.
public function __construct(Request $request, User $user, ....)
{
//save them into class variables to access them later
$this->request = $request;
$this->user = $user;
}
Otherwise you can directly put your validation logic into the passes method:
public function passes($attribute, $value){
//some code
return #myCondition
}
Last you are able to specify the message if the validation fails.
public function message()
{
return 'Your message';
}
To use your rule simply add it to your rules array:
$rules = [
'my_attribute' => [new MyCustomRule(),...],
]
At last, I have solved this problem using FormRequest and AppServiceProvider. Thought this would help others who come to this place.
First I have created FormRequest validator using following artisan command.
php artisan make:request StoreRequisition
Then added primary validation rules and messages into it.
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StoreRequisition extends FormRequest {
public function authorize() {
return true;
}
public function rules() {
$rules = [
'txtTravelDate' => 'required|date_format:Y-m-d|after_or_equal:today',
'txtTimeFrom' => 'required|date_format:H:i|travel_time_validate',
'txtTimeTo' => 'required|date_format:H:i',
];
return $rules;
}
public function messages() {
return [
'txtTravelDate.required' => 'Travel date is required!',
'txtTravelDate.date_format' => 'Invalid format for Travel Date!',
'txtTravelDate.after_or_equal' => 'Travel Date should be today or later!',
'txtTimeFrom.required' => 'Time From is required!',
'txtTimeFrom.date_format' => 'Invalid format for Time From!',
'txtTimeFrom.travel_time_validate' => 'Invalid time selected!',
'txtTimeTo.required' => 'Time To is required!',
'txtTimeTo.date_format' => 'Invalid format for Time To!',
'listFunction.required' => 'Department to be selected!',
'txtPickLoc.required' => 'Pickup Location is required!',
'txtDropLoc.required' => 'Drop Location is required!',
'listPurpose.required' => 'Travel Purpose to be selected!'
];
}
}
Then inside app\Providers\AppServiceProvider, added the extra validation logic.
public function boot() {
Validator::extend(
'travel_time_validate',
function ($attribute, $value, $parameters, $validator) {
$inputs = $validator->getData();
/* convert time to moments */
$momentFrom = strtotime($inputs['txtTravelDate'] . " " . $inputs['txtTimeFrom']);
$momentTo = strtotime($inputs['txtTravelDate'] . " " . $inputs['txtTimeTo']);
$result = true;
if ($momentFrom >= $momentTo) {
$result = false;
}
return $result;
}
);
}
My Controller:
public function store(StoreRequisition $request, Requisition $requisitionObj) {
$validatedData = $request->validated();
/* store form data into requisition object */
$requisitionObj->requester_id = Auth::user()->id;
$requisitionObj->travel_date = $request->txtTravelDate;
$requisitionObj->time_from = $request->txtTimeFrom;
$requisitionObj->time_to = $request->txtTimeTo;
$requisitionObj->purpose_id = $request->listPurpose;
/* Finally save the record into the database */
$requisitionObj->save();
return redirect()->route('requisitions.index');
}
Example how make custom rule for validation in Laravel 8.x / Lumen 8.x.
public static function rules(){
return [
'number' => [
'required', 'min:1', 'max:30', 'string', self::testNumber(),
],
];
}
public static function testNumber(){
return function($attribute, $value, $fail){
if ($value === 'foo'){
$fail('The '.$attribute.' is invalid.');
}
};
}

Laravel 5 validate string with multiple dates comma separated

How can i validate this string with the laravel validation? I want to check if the dates between the commas is a date.
2017-11-11,2017-12-11-2017,2017-13-11
In reply to your comment. Yes laravel can do that, by creating a request class like this.
<?php namespace App\Laravel\Requests\Backoffice;
use Session,Auth, Input;
use App\Laravel\Requests\RequestManager;
class DateRequest extends RequestManager{
public function rules(){
$rules = [
//validate if the value is a date and check the date_format must be in "Y-d-m" form
'date' => 'date|date_format:"Y-d-m"',
];
return $rules;
}
public function messages(){
return [
'date' => "Invalid date.",
'date_format' => "Invalid date format.",
];
}
}
You can use explode() array function, It split a string and convert it to array.
$date_string = '2017-11-11,2017-12-11-2017,2017-13-11';
//Split the $date_string
$dates = explode(',',$date_string);
//get the values of the $dates variable
foreach($dates as $date){
//Check if the $date values are valid or not
if(Carbon::createFromFormat('DATE FORMAT',$date) !== false){
//valid date format
}else{
//invalid date format
}
}
You can do it with using Rule Objects more elegant, next time you can reuse this validation/rule.
Run php artisan make:rule Stringdate
app/Rules/Stringdate.php file will be generated.
change passes method like this
public function passes($attribute, $value)
{
if(!$value){
return false;
}
$dates = explode(',',$value);
foreach ($dates as $date){
if(preg_match("/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/",$date) < 1){
return false;
}
}
return true;
}
The validation you can make in controller, for ex.
$this->validate(request(),['data' => ['required',new Stringdate()]]);
(data is your attribute name)
in that case you should create a custom validator for the comma delimiter date string so can still use the Request class.
public function validateSampleCustom($attribute, $value, $parameters){
...do you custom code here
...where value is the passed value from the input field
...parameters are the value after the semi_colon in your request eg : (sample_custom:param1,param2,...,paramn)
}
i can show you some custom validator
public function validateOldPassword($attribute, $value, $parameters){
if($parameters){
$user_id = $parameters[0];
$user = User::find($user_id);
return Hash::check($value,$user->password);
}
return FALSE;
}
I just want to clarify your concern so we can help you with your issues. and i use this to my Request class by calling it this way
'password' => "required|old_password",
and then to include the custom validator you should call the Validator::resolver in your AppServiceProvider to bind your custom validator.
public function boot()
{
// Schema::defaultStringLength(191);
Validator::resolver(function($translator, $data, $rules, $messages)
{
return new CustomValidator($translator, $data, $rules, $messages);
});
}

Laravel 4 validator for password field in edit account

I need to check if a user has posted the same password as the one in the database. Field for old password is 'oldpass'. The custom validator i created is called 'passcheck'. It should fail or pass accordingly.
My UsersController code below doesnt work. What could have I have done wrong?
$rules = array(
'oldpass' => 'passcheck',
);
$messages = array(
'passcheck' => 'Your old password was incorrect',
);
Validator::extend('passcheck', function($attribute, $value, $parameters)
{
if(!DB::table('users')->where('password', Hash::make(Input::get('oldpass')))->first()){
return false;
}
else{
return true;
};
});
$validator = Validator::make($inputs, $rules, $messages);
You should use something like this,
$user = DB::table('users')->where('username', 'someusername')->first();
if (Hash::check(Input::get('oldpass'), $user->password)) {
// The passwords match...
return true;
}
else {
return false;
}
So, you have to get the record using username or any other field and then check the password.
#lucasmichot offered even shorter solution:
Validator::extend('passcheck', function ($attribute, $value, $parameters)
{
return Hash::check($value, Auth::user()->getAuthPassword());
});
I would make it like this:
/**
* Rule is to be defined like this:
*
* 'passcheck:users,password,id,1' - Means password is taken from users table, user is searched by field id equal to 1
*/
Validator::extend('passcheck', function ($attribute, $value, $parameters) {
$user = DB::table($parameters[0])->where($parameters[2], $parameters[3])->first([$parameters[1]]);
if (Hash::check($value, $user->{$parameters[1]})) {
return true;
} else {
return false;
}
});
This validator rule will make database query to check current user's password
You can make it even shorter and save query:
Validator::extend('passcheck', function ($attribute, $value, $parameters) {
return Hash::check($value, Auth::user()->getAuthPassword());
});
Please dont tie your rule to an Html element. Use the parameters Laravel provides to create your custom rules. This would be (asuming that you have a user authenticated):
Validator::extend('passcheck', function($attribute, $value, $parameters) {
return Hash::check($value, Auth::user()->password); // Works for any form!
});
$messages = array(
'passcheck' => 'Your old password was incorrect',
);
$validator = Validator::make(Input::all(), [
'oldpass' => 'passcheck',
// more rules ...
], $messages);

Categories