Laravel 4: Validate start and end date with before and after validation

18,471

Solution 1

I know that it is a question about Laravel 4 BUT if you are using Laravel 5.3 now you can use something like:

$rules = array(

   'date_start' => 'required|date_format:Y-m-d|before_or_equal:date_end',
   'date_end' => 'required|date_format:Y-m-d|after_or_equal:date_start'

       );

    $validator = Validator::make($request->all(), $rules);

Solution 2

Laravel 5:

Here is more extensive approach that follows modern principles and is more Laravel-like. This is a little more complex but still easy to follow and the end results is much cleaner.

Let's start by changing a few things. Let's reduce this to the specific problem, use newer array syntax and apply formatting.

$rules = [
  'from_date' => [
    'before:'.Input::get('to_date') // This is what we will learn to do
  ],
  'to_date' => [ 
    'after:'.Input::get('from_date') // Do this one on your own
  ]
];

Now let's create a new Request with php artisan make:request StoreWhateverRequest. This will create the App/HTTP/Request/StoreWhateverRequest.php file. Open that and place your rules in the return array of the rules() function.

return [
   'from_date'       => 'date',
   'to_date'         => 'date|after_field:from_date'
 ];

This will not work yet because after_field isn't available to use yet. Let's create that. We need a new class that extends validator. You can place it in app/Services. We need something similar to:

<?php namespace App\Services;

use Illuminate\Validation\Validator;
use Carbon\Carbon;

class AfterFieldValidator extends Validator {
  public function validateAfterField($attribute, $value, $parameters)
  {
    return Carbon::parse($value) > Carbon::parse($this->data[$parameters[0]]);
  }
}

In the above we have: $attribute which is the name of the field we are checking (to_date), $value is the value of the field we are checking and $parameters is the parameters we passed to the Validator(from_date) seen in 'to_date' => 'date|afterField:from_date'. We also need the other data fields passed to the Validator, we can get these with $this->data. Then we just have to preform the logic appropriately. You really don't even need Carbon here but be sure to parse the string so we don't do string comparison.

Now we need to load this into the application. To do this put the below code inside the boot() function in app/Providers/AppServiceProviders.php.

Validator::resolver(function($translator, $data, $rules, $messages)
{
  return new afterFieldValidator($translator, $data, $rules, $messages);
});

The final step is easiest. Just inject and instance of StoreWhateverRequest into our Controller.

...
public function store(StoreWhateverRequest $request)
{
...

All done. I feel this is a pretty SOLID way to solve the problem.

Solution 3

Please use the below code in laravel 5.2 and it works fine for validating start and end date.

$this->validate($request, [
            'start_date' => 'required|before:end_date',
            'end_date' => 'required',

        ]); 

Solution 4

Just came across this and thought I'd share an answer I found: Compare attributes in validation

Basically, you'd create a new Validator that extends Illuminate\Validation\Validator and write a custom rule in there:

public function validateEndAfter($attribute, $value, $parameters) {
    $start_date = $this->getValue($parameters[0]); // get the value of the parameter (start_date)
    return (strtotime($value) > strtotime($start_date));
}

then in your validator use the new rule:

$rules = [
    'start_date'  => 'required',
    'end_date'=> 'required|end_after:start_date',
]

Solution 5

Anyhow,

I did as like this. So that even if any date in the form is empty that will auto fill and check the validation

$inputs = Input::all();
if(!empty($inputs))
{
    $default_date_arr = array('from_date' => date('Y-m-d', strtotime('-1 days')), 'to_date' => date('Y-m-d'));
    $inputs = $inputs+$default_date_arr;
}
$rules = array('from_date' => array('sometimes','date_format:"Y-m-d"', 'before:'.$to_date) ,
                        'to_date' => array('sometimes','date_format:"Y-m-d"', 'after:'.$from_date ) );
$validator = Validator::make($inputs,$rules);
if($validator->fails())
{ ... }

This may not be the answer for what i asked. But i needed just a way to finish this. May be will helpful for others.

Share:
18,471
siddiq
Author by

siddiq

Updated on July 16, 2022

Comments

  • siddiq
    siddiq almost 2 years

    I want to validate two date fields in a form which is from_date and end_date. Need to check from_date is less than end_date.

    $rules = array('from_date' => array('sometimes','date_format:"Y-m-d"', 'before:'.Input::get('to_date') ),
                            'to_date' => array('sometimes','date_format:"Y-m-d"', 'after:'.Input::get('from_date') ) );
    

    This is what i tried. But that does not work. If i give the to_date as empty value it will through the error.