We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Custom date validator

Hello everyone. I am trying to implement a custom validator in Phalcon to check if a date is of a correct format but also to check if the day actually existed (for example I am not allowing the 30th of Feb). But I am kind of stuck. I need this validator to validate a form field. Which methods should I implement to make it work as a usual Phalcon validator (it has to display a message passed, cancel other validators to validate if it fails and so on). This is what I currently have

<?php

use Phalcon\Validation\Validator,
    Phalcon\Validation\ValidatorInterface,
    Phalcon\Validation\Message;

class DateValidator extends Validator implements ValidatorInterface 
{

    public function __construct($options = null) 
    {

        parent::__construct();
        if ($options != null) 
        {
            $this->_options = $options;
        }
    }

    /**
     * Executes the validation
     *
     * @param Phalcon\Validation $validator
     * @param string $attribute
     * @return boolean
     */
    public function validate($validator, $attribute)
    {

    }
}

This was mostly copied from here. I don't quite understand how the the validate method has to work, what are these params ($validator, $attribute) for ? Which methods should I also impement to make it work as a normal phalcon validator. Thanks in advance.



26.3k
Accepted
answer
edited Aug '14

Hi!

  1. You should implement validate() method.
  2. Method validate() must return true or false.
  3. Your class should extend Phalcon\Validation\Validator or implement Phalcon\Validation\ValidatorInterface (or both, I am not sure, I am doing both).
  4. So as you see here https://docs.phalcon.io/en/latest/api/Phalcon_Validation_Validator.html method validate() is defined as abstract so must be defined.
  5. Phalcon will execute your validate() method. First argument ($validator) is object of Phalcon\Validation class from here https://docs.phalcon.io/en/latest/api/Phalcon_Validation.html. One of its method is getValue(). You will need this method to obtain the date value. Second argument ($attribute) is the name of the field from your form.

So my implementation would be:


use Phalcon\Validation\Validator,
    Phalcon\Validation\ValidatorInterface,
    Phalcon\Validation\Message;

class AwesomeDateValidator extends Validator implements ValidatorInterface {

    // constructor is defined only because you wanted to have "cancelOnFail" true, 
    // If you don't want this, then the implementation of constructor is not necessary
    public function __construct($options = null) {

        //pass options to original constructor
        parent::__construct($options);

        $this->setOption("cancelOnFail",true);

    }

    public function validate($validator, $attribute) {

        var_dump($validator);//delete this line, it's for you to see what it is
        var_dump($attribute);//delete this line, it's for you to see what it is

        //obtain date value
        $date = $validator->getValue($attribute);

        if($date === "awesomedate"){
            return true;
        }

        //if we are here it means that date is wrong

        //first, check if message was provided with options 
        $message = $this->getOption('message');
        if (!$message) {
            //message was not provided, so set some default
            $message = "This date is not awesome!";
        }

        //add message object 
        $validator->appendMessage(new Message($message, $attribute, 'IsAwesomeDate'));

        return false;

    }
}

I've not extended any validation yet but I've just come up with this following the documentation here: https://docs.phalcon.io/en/latest/reference/validation.html#validators

Let me know if it works, I'm assuming you have basic understanding of PHP.

class DateValidator extends \Phalcon\Validation\Validator implements \Phalcon\Validation\ValidatorInterface
{
    public function validate($validator, $attribute)
    {
        $date = date_parse_from_format('d/m/Y', $validator->getValue($attribute));
        if (($date['error_count'] + $date['warning_count']) > 0) {
            $message = $this->getOption('message');

            if (!$message) {
                $message = 'The date entered was in valid, must be in format dd/mm/yyyy';
            }

            $validator->appendMessage(new \Phalcon\Validation\Message($message, $attribute, 'Date'));

            return false;
        }

        return true;
    }
}

It doesn't return true, that's adding together the number of errors/warnings encountered when parsing the date, so if they're greater than 0 it'll be invalid.



26.3k
edited Aug '14

I have changed a little my code - there ware some errors made when copy/paste my code.

In my code, when sb will enter "awesomedate" in a form field then the validator will not find any errors. If it will be sth else, then message will be generated.



28.4k

Great. Thanks guys a lot. You saved my life :)



14.8k

What if i need to compare Dates entered into the form like Start Date and End Date, e.g.

  • Start Date is not equal to End Date
  • Start Date is not greater than End Date

Can i provide more than 1 attribute into my Validation class?

edited Apr '15

Turn them into DateTime objects and use comparison operators for example:

$date1 = new \DateTime($timestamp);
$date2 = new \DateTime($timestamp2);

if ($date1 > $date2) {
    // $date1 is after $date2
}

if ($date1 === $date2)  {
    // these are the same date
}