Compare 2 dates from input in validation

Note: a better way to achieve this was posted here

This tutorial will show you how to create a custom validation rule in Laravel to compare 2 dates, e.g. when you want to check if a start date is before end date.

First create a file named Validator.php in libraries and comment(or remove) the alias from config/application.php. This will overwrite the Validation class, the autoload from Laravel will search Validator in libraries.

Next add the following code to the file:

<?php

class Validator extends Laravel\Validator
{

    /**
     * Validate that a date is before another one
     *
     * @param  string  $attribute
     * @param  mixed   $value
     * @param  array   $parameters
     * @return bool
     */
    public function validate_before_date($attribute, $value, $parameters)
    {

        return strtotime( $value ) < strtotime( $this->attributes[ $parameters[0] ] );

    }//validate_before_date

    /**
     * Replace all place-holders for the different rule.
     *
     * @param  string  $message
     * @param  string  $attribute
     * @param  string  $rule
     * @param  array   $parameters
     * @return string
     */
    protected function replace_before_date($message, $attribute, $rule, $parameters)
    {

        return str_replace(':other', $this->attribute($parameters[0]), $message);

    }//replace_before_date

}//end class

Explications:
validate_before_date($attribute, $value, $parameters)

$value is the value of the date you want to compare (e.g. start date)
$parameters will be an array of values passed to validations after “:” (e.g. for ‘start_date’ => ‘before_date:end_date’, $parameters[0] will be equal to ‘end_date’).
$this->attributes[] contains all inputs(The first parameter from Validator::make())

replace_before_date($message, $attribute, $rule, $parameters)

This method is used when generating error message, we want to replace “:other” with $parameters[0] which will be equal to the input we want to compare against.
To add the custom error message:

$messages = array(
    'before_date' => ":attribute must be before :other"
);

To use it pass it as the third parameter:


$validation = Validator::make($inputs, $rules, $messages);

Or add it to the validation language file in custom array:

 'custom' => array(
          'before_date' => ":attribute must be before :other"
 )
 

Example

Copy paste the code below to test it, the validation should fail

$inputs = array(
  'start_date' => '2013-01-20',
  'end_date'   => '2013-01-15'
);

$rules = array(
  'start_date' => 'required|before_date:end_date',
  'end_date'   => 'required'
);

$messages = array(
  'before_date' => ":attribute must be before :other"
);

$validation = Validator::make($inputs, $rules, $messages);

if( $validation->fails() )
{

  echo '<pre>';
  print_r($validation->errors);
  echo '</pre>';

}//if it didn't validate
Advertisements

2 thoughts on “Compare 2 dates from input in validation

  1. I don’t know when it was added, but nowadays you can use the “after” and “before” validation rules.

    When there are two date fields, say “start_date” and “end_date” and the “end_date” must be after the “start_date” you could do:

    end_date’ => array(‘date’, ‘after:begin’)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s