Search code examples
phpvalidationcakephpcakephp-2.x

Two custom validation rules for same two fields not working when both are present in CakePHP 2


I have a $validate array in a model with two custom validation rules. In my 'add' and 'edit' actions, if the user does not provide either a Need Date OR does not check a box labeled "Not Required," the application should throw a warning. If the user provides BOTH a Need Date AND checks the box, the app should throw a warning saying that they must choose one or the other.

My problem is that these rules do not work at all if they're both present. If I comment one or the other out, the uncommented rule works fine.

Here is the code from the model:

public $validate = array(
'need_date' => array(
        'allowEmpty' => true,
        'rule' => 'checkNeedDate',
        'message' => 'Please enter a Need Date or check the box if not required.'
    ),
    'no_need_date' => array(
        'allowEmpty' => true,
        'rule' => 'checkNeedDate',
        'message' => 'Please enter a Need Date or check the box if not required.'
    ), 
    'need_date' => array(
        'allowEmpty' => true,
        'rule' => 'oneOrTheOther',
        'message' => 'Please enter EITHER \'Not Required\' OR a Need Date.'
    ),
    'no_need_date' => array(
        'allowEmpty' => true,
        'rule' => 'oneOrTheOther',
        'message' => 'Please enter EITHER \'Not Required\' OR a Need Date.'
    )
);

And here are the validation functions from the same model:

//Make sure that either the Requested Need Date field is filled in OR that the Not Required checkbox has been checked
function checkNeedDate($field) {
    if(!empty($this->data[$this->alias]['need_date']) || !empty($this->data[$this->alias]['no_need_date'])) {
        return true;
    } else {
        return false;
    }
}

//Make sure that the user has not filled in the Need Date field AND checked the Not Required box
function oneOrTheOther($field) {
    if(!empty($this->data[$this->alias]['need_date']) && !empty($this->data[$this->alias]['no_need_date']) ) {
        return false;
    } else {
        return true;
    }
}

What might I be doing wrong here?

EDIT: The oneOrTheOther() function works in both my 'add' and 'edit' actions when checkNeedDate() is present. checkNeedDate() appears to be the problem when it isn't by itself.


Solution

  • TLDR: Check the "Multiple Rules per Field" area in the CakePHP 2 Book. (You're overwriting the first value by using multiples of the same key).


    More Details:

    This is a standard array() issue and one of those minor things often overlooked (Don't worry, we've all done it at least once).

    If you set a key that's already set, it will overwrite the previous key's value.

    Example:

    $food = [
        'pizza' => 'yuck',
        'vegetables' => 'meh',
        'pizza' => 'OMGYES!',
    ];
    

    The resulting array will be:

    $food = [
        'pizza' => 'OMGYES!',
        'vegetables' => 'meh',
    ];
    

    Try this:

    public $validate = array(
        'need_date' => [
            'customCheck' => [
                'allowEmpty' => true,
                'rule' => 'checkNeedDate',
                'message' => 'Please enter a Need Date or check the box if not required.'
            ],
            'needDate' => [
                'allowEmpty' => true,
                'rule' => 'oneOrTheOther',
                'message' => 'Please enter EITHER \'Not Required\' OR a Need Date.'
            ]
        ],
        'no_need_date' => [
            'checkNeedDate' => [
                'allowEmpty' => true,
                'rule' => 'checkNeedDate',
                'message' => 'Please enter a Need Date or check the box if not required.'
            ],
            'oneOrTheOther' => [
                'allowEmpty' => true,
                'rule' => 'oneOrTheOther',
                'message' => 'Please enter EITHER \'Not Required\' OR a Need Date.'
            ]
        ],
    );
    

    Notice each rule is in it's own, uniquely named key within the SAME field-name key.