Cakephp 4: Conditional validation using callback

I have two fields on my form: one for a date and one checkbox if the date is not required:

echo $this->Form->control('need_date', ['label' => 'Requested Need Date', 'empty' => true]); 
echo $this->Form->control('no_need_date', ['type' => 'checkbox', 'label' => 'Not Required', 'empty => true]); 

If the user checks the ‘Not Required’ checkbox, then they do not have to provide a need date, so BOTH of these controls cannot be empty. I’ve tried using a callback in my model to reflect this:

        ->notEmptyDate('need_date', 'Please enter the Need Date, or check \'Not Required\' if no need date.', function ($context) {
            if (!isset($context['data']['no_need_date'])) {
                return false;
            } else {
                return true;

The problem: Validation fails even if I check ‘Not Required’, and the validation error message is displayed. If I change the condition to empty($context['data']['no_need_date']) or $context['data']['no_need_date'] == false, then validation gets skipped entirely. Where am I going wrong? The no_need_date field is nullable in my database and has no default value.

Could be a falsey thing. or isset($context[‘data’][‘no_need_date’] could be set with the value ‘false’ so that the isset passes. Replace your whole if statement with: -

return $context['data']['no_need_date'] === 'checked';

or something like that. May need to debug that value to see what is really being passed when both checked and unchecked.

Also, your code doesn’t have a closing quote on your 'empty => true]); - no quote after the word empty.

Thanks for the advice. Unfortunately, this did not solve the problem.

Debugging shows that no_need_date has a value of ‘0’ when unchecked and a value of ‘1’ when checked. But no matter how I format my callback, it doesn’t seem to care.

(The missing end quote was a backspacing error.)


Got it working this way:

        ->notEmptyString('need_date', 'Please enter the Need Date, or check \'Not Required\' if no need date.', function ($context) {
            return $context['data']['no_need_date'] === '0' ? true : false;

Originally, I was trying to get it to evaluate to ‘false’ to trigger the validation error, and to ‘true’ to get it to pass. Reversing them fixed it.

This is more of a PHP question, but what is the difference between

return $context['data']['no_need_date'] === '0' ? true : false;


return $context['data']['no_need_date'] === '0';

without the ternary operator? I would have thought the === condition would return a boolean typed value. (Old school: seeing a Boolean condition return explicitly stated true or false makes my eye twitch, hehe - I’m still sometimes lost with falsey stuff!)

I wish I knew! It baffles me, too. But only the the ternary statement worked in my model.