Search code examples
zend-formzend-validatezend-form-sub-form

How to validate >1 field at a time, in a Zend sub-form?


I've created a 3 screen "wizard" using the Zend_Form_SubForm example from the online reference documentation.

The requirement I'm having trouble meeting is this: If fields 1, 2, & 3 of the first screen are already in the database, notify the user that they are trying to add a duplicate record. Each of those fields has their own validators. Somehow I need to add this "group validator".

So, at its most basic level, I'm trying to do:

if($field_1_not_in_db && $field_2_not_in_db && $field_3_not_in_db){ 
   return true;//validation OK 
} else { 
   return false;//invalid data
}

I am coming up against several issues, though: 1) Because it applies to multiple fields, I don't know which field to attach it to. Error messages appear beside the field they are attached to, so this is important... unless I can get these "multi-field validator" errors to appear at the top of the screen, which would be ideal. 2) My validator is only receiving a single value (the value of the field I attach it to, not the values of the multiple fields it is supposed to validate). 3) I provide a link to the original (non-duplicate) record in the error message, but it escapes the link, and I can't figure out how to get around that.

The setup I'm currently using (below) actually executes fine, but NewPlace validator receives $_POST['city_fk'] as $fields, instead of the desired group of posted values.

$city_fk = new Zend_Form_Element_Select('city_fk');
$cities = array();
$city_fk->setMultiOptions($cities)
        ->setLabel('City')
        ->setDescription('The city this place is in')
        ->setRequired(true);

$v = array(
      'place_is_unique' => array(
                'NewPlace',
                'fields' => array('place_name','phone_number','phone_extension','street','post_code_name'),
        )
    );
$city_fk->addValidators($v);

$addressSubForm->addElement($city_fk);

class My_Validate_NewPlace extends Zend_Validate_Abstract
{ 
    public function isValid($fields)
    {  
        $result = false;

    if(!$result)
        {
            $this->_error('sorry, this is duplicate data. see it <a href="linktoduplicate">here</a>');
        return false;
        }

        return true;
    }
}

Solution

  • This won't help you decide which field to attach the validation to, but... There is a thing called a "validation context" that helps. When you create your custom validator or form IF you specify a second optional parameter ($context = null), then Zend will auto-populate this with the entire array of posted data, which you can use to incorporate other fields values into your validation. Here's a very basic example:

    $city_name = new Zend_Form_Element_Text('city_name');
    
    $place_name = new Zend_Form_Element_Text('place_name');
    $place_name->addValidator('NewPlace');
    
    class My_Validate_NewPlace extends Zend_Validate_Abstract
    { 
        public function isValid($value, **$context = null**)
        {  
            if(trim($value)!='' && trim($context['city_name']) != '')
            { 
                return true;
            }
    
            return false;
        }
    }