I've got a form that requires some really complex and custom validation for each sub-section in it. Like for example, in one section it needs to pass if all boxes are blank, but if not then box #1 or #2 needs to be filled in, box #5 is required but only if #3's value is less than #4, and #6 is optional but only if #7 checked on a Thursday, etc etc.

The data's not part of a model either, so can't handle it in there. So the easiest way to handle it I figure would be with 1 single custom validator attached to the form that checks everything and sets the errors accordingly, something like this:

class CrazyValidation extends Phalcon\Validation\Validator {
    public function validate($validator, $attribute) {
        //get the values of each box
        $box1 = $validator->getValue("box1");   
        $box2 = $validator->getValue("box2");   
        $box3 = $validator->getValue("box3");
        $box4 = $validator->getValue("box4");
        $box5 = $validator->getValue("box5");

        $passed = true;

        //pass if all blank
        if(!$box1 && !$box2 && !$box3 && !$box4) return true;

        //either box 1 or 2
        if(!$box1 && !$box2) {
            $validator->appendMessage(new Message('box 1 or 2 is required', 'box1'));
            $passed = false;
        }

        //box5 is required if 3 and 4
        if(!$box5 && $box3 && $box4) {
            $validator->appendMessage(new Message('box 5 is required', 'box5'));
            $passed = false;
        }

        //box3 must be less than 4 if box5 is checked
        if($box5 && ($box3 >= $box4)) {
            $validator->appendMessage(new Message('box 3 must be less than 4', 'box3'));
            $passed = false;
        }

        return $passed;
    }
}

So if there's an error on box1, $validator->appendMessage() seems to put the message in ok, and validation fails properly on $form->isValid() in the controller. However in the view $form->hasMessagesFor('box1') is false and $form->getMessagesFor('box1') returns nothing, even though var_dump($form->getMessages()) shows that it's there. Is there anything else I need to set to get it to work? Or is there just a completely better way to handle it?