I am trying to validate Zend_Form which has several optional fields and I want at least one of them to be filled in. In my case I have mobile, home and office phone numbers and I want at least one of them to be provided.
I am trying to achieve this though Validation Context (as suggested here) by creating custom validator which extends Zend_Validate_Abstract. The problem is that if all optional fields are empty they are missing from the form $context (passed to the validator class) and this way not validated at all. So if you fill any or several of the three options (mobile, home, work) they are all going to be validated (which is fine, but for this no custom validator is needed), but if you fill none of them, there is no option to force the customer to fill at least one of the fields (which is my aim).
Here is what I have:
1. my form
<?php
class Application_Form_Application extends Zend_Form {
public function init() {
$this->setName('application');
// attach sub forms to main form
$this->addSubForms(array(
'application' => $this->application(),
...
));
}
private function application() {
$application = new Zend_Form_SubForm();
// custom phone validation
$phone_validation = array('phone_mobile' => 'Mobile', 'phone_home' => 'Home', 'phone_work' => 'Work');
// phone mobile
$app['phone_mobile'] = new Zend_Form_Element_Text('phone_mobile');
$app['phone_mobile']->setLabel('Mobile')
->addFilter('StripTags')
->addFilter('StringTrim')
->addValidator('Regex', false, array('/^[0-9]{8}$/i'))
->addValidator(new Application_Form_PhoneMobileHomeWork($phone_validation), false);
// phone home
$app['phone_home'] = new Zend_Form_Element_Text('phone_home');
$app['phone_home']->setLabel('Home')
->addFilter('StripTags')
->addFilter('StringTrim')
->addValidator('Regex', false, array('/^[0-9]{8}$/i'))
->addValidator(new Application_Form_PhoneMobileHomeWork($phone_validation), false);
// phone work
$app['phone_work'] = new Zend_Form_Element_Text('phone_work');
$app['phone_work']->setLabel('Work')
->addFilter('StripTags')
->addFilter('StringTrim')
->addValidator('Regex', false, array('/^[0-9]{8}$/i'))
->addValidator(new Application_Form_PhoneMobileHomeWork($phone_validation), false);
$application->AddElements($app);
}
}
?>
2. custom validator
<?php
class Application_Form_PhoneMobileHomeWork extends Zend_Validate_Abstract {
const NOT_PRESENT = 'notPresent';
protected $_messageTemplates = array(
self::NOT_PRESENT => 'At least one contact phone shall be provided!'
);
protected $_listOfFields;
public function __construct(array $listOfFields) {
$this->_listOfFields = $listOfFields;
var_dump($listOfFields);exit;
}
public function isValid($value, $context = null) {
var_dump($context);exit;
...
}
?>
The validator always passes though the first dump ($listOfFields), but if I remove it, isValid() is never called unless some data is typed into some of the phone fields (which we want to prevent).
When I checked further I found a solution in extending the Zend_Validate class by passing empty fields to the $context parameter, but I would like to have a better solution if someone knows any.
Concluding it in short - how to validate certain form, forcing the user to fill at least one out of several optional fields?