views:

2624

answers:

7

I have created a form to add a user to a database and make user available for login.

Now I have two password fields (the second is for validation of the first). How can I add a validator for this kind of validation to zend_form?

This is my code for the two password fields:

 $password = new Zend_Form_Element_Password('password', array(
  'validators'=> array(
   'Alnum',
   array('StringLength', array(6,20))
   ),
  'filters' => array('StringTrim'),
  'label'  => 'Wachtwoord:'
  ));

 $password->addFilter(new Ivo_Filters_Sha1Filter());

 $password2 = new Zend_Form_Element_Password('password', array(
  'validators'=> array(
   'Alnum',
   array('StringLength', array(6,20))
   ),
  'filters' => array('StringTrim'),
  'required' => true,
  'label'  => 'Wachtwoord:'
  ));
 $password2->addFilter(new Ivo_Filters_Sha1Filter());

Thank you,

Ivo Trompert

A: 

You could try extending Zend_Validate_Abstract to create a validator that ensures one value equals another, and then apply that validator to the password confirm field.

For input validation you could also investigate using Zend_Filter_Input.

Rob Hruska
Please consider deleting this as the following answer is spot on: http://stackoverflow.com/questions/347856/zend-form-how-to-check-2-fields-are-identical/3782388#3782388
wilmoore
+1  A: 

here is how i done this :)

create first pass input then crate second pass input and add Identical validator with data from previous password input.

$password_2->addValidator('identical', false, $this->_request->getPost('password'));
Irmantas
This only works if you've add the validator in the controller. This won't work inside the form because you won't have access to the request.
Andrew
This is bad practice as the controller is now responsible for adding the validation criteria.
wilmoore
+2  A: 

When I was looking for the same, I found this very well working generic Validator for Identical Fields. I don't find it now so I just post the code...

<?php

class Zend_Validate_IdenticalField extends Zend_Validate_Abstract {
  const NOT_MATCH = 'notMatch';
  const MISSING_FIELD_NAME = 'missingFieldName';
  const INVALID_FIELD_NAME = 'invalidFieldName';

  /**
   * @var array
  */
  protected $_messageTemplates = array(
    self::MISSING_FIELD_NAME  =>
      'DEVELOPMENT ERROR: Field name to match against was not provided.',
    self::INVALID_FIELD_NAME  =>
      'DEVELOPMENT ERROR: The field "%fieldName%" was not provided to match against.',
    self::NOT_MATCH =>
      'Does not match %fieldTitle%.'
  );

  /**
   * @var array
  */
  protected $_messageVariables = array(
    'fieldName' => '_fieldName',
    'fieldTitle' => '_fieldTitle'
  );

  /**
   * Name of the field as it appear in the $context array.
   *
   * @var string
   */
  protected $_fieldName;

  /**
   * Title of the field to display in an error message.
   *
   * If evaluates to false then will be set to $this->_fieldName.
   *
   * @var string
  */
  protected $_fieldTitle;

  /**
   * Sets validator options
   *
   * @param  string $fieldName
   * @param  string $fieldTitle
   * @return void
  */
  public function __construct($fieldName, $fieldTitle = null) {
    $this->setFieldName($fieldName);
    $this->setFieldTitle($fieldTitle);
  }

  /**
   * Returns the field name.
   *
   * @return string
  */
  public function getFieldName() {
    return $this->_fieldName;
  }

  /**
   * Sets the field name.
   *
   * @param  string $fieldName
   * @return Zend_Validate_IdenticalField Provides a fluent interface
  */
  public function setFieldName($fieldName) {
    $this->_fieldName = $fieldName;
    return $this;
  }

  /**
   * Returns the field title.
   *
   * @return integer
  */
  public function getFieldTitle() {
    return $this->_fieldTitle;
  }

  /**
   * Sets the field title.
   *
   * @param  string:null $fieldTitle
   * @return Zend_Validate_IdenticalField Provides a fluent interface
  */
  public function setFieldTitle($fieldTitle = null) {
    $this->_fieldTitle = $fieldTitle ? $fieldTitle : $this->_fieldName;
    return $this;
  }

  /**
   * Defined by Zend_Validate_Interface
   *
   * Returns true if and only if a field name has been set, the field name is available in the
   * context, and the value of that field name matches the provided value.
   *
   * @param  string $value
   *
   * @return boolean 
  */ 
  public function isValid($value, $context = null) {
    $this->_setValue($value);
    $field = $this->getFieldName();

    if (empty($field)) {
      $this->_error(self::MISSING_FIELD_NAME);
      return false;
    } elseif (!isset($context[$field])) {
      $this->_error(self::INVALID_FIELD_NAME);
      return false;
    } elseif (is_array($context)) {
      if ($value == $context[$field]) {
        return true;
      }
    } elseif (is_string($context) && ($value == $context)) {
      return true;
    }
    $this->_error(self::NOT_MATCH);
    return false;
  }
}
?>
tharkun
Please consider deleting this as the following answer is spot on: http://stackoverflow.com/questions/347856/zend-form-how-to-check-2-fields-are-identical/3782388#3782388
wilmoore
@Wilmoore: Deleting is not the right thing to do here as my answer is still valid since it can help some people under certain circumstances. The OP should unaccept my outdated answer and accept the answer linked by you.
tharkun
@tharkun, good point. I agree.
wilmoore
A: 

Edit: This answer is being left for history's sake, this is now the correct answer

The Zym Framework (a Zend Framework extension) has a built in validator for this exact purpose. Try out the Zym_Validate_Confirm class.

leek
Please consider deleting this as the following answer is spot on: http://stackoverflow.com/questions/347856/zend-form-how-to-check-2-fields-are-identical/3782388#3782388
wilmoore
I will leave my answer for history's sake. Please notice I wrote this answer almost 2 years ago.
leek
A: 

Greetings Gang,

The code posted by tharkun is actually from my page, although I've since added an information block to the top the class to help alleviate such issues. However, I followed leek's link to the Zym Project and its validator implementation and found that is indeed similar to mine. Although is provides fewer options (e.g. one may not set the title text for the sake of messages), it is quite functional and (as of the writing of this post) the project is well supported and in active development. Pick the one that works best for your needs. =o)

Regards,

Sean P. O. MacCath-Moran
www.emanaton.com

Please consider deleting this as the following answer is spot on: http://stackoverflow.com/questions/347856/zend-form-how-to-check-2-fields-are-identical/3782388#3782388
wilmoore
+1  A: 

These two answers:

http://stackoverflow.com/questions/347856/zend-form-how-to-check-2-fields-are-identical/2207224#2207224

http://stackoverflow.com/questions/347856/zend-form-how-to-check-2-fields-are-identical/348782#348782

are close; however, they either require direct access to the $_POST super global or the $request object. Neither of which belong in your form class/object.

The following is a much cleaner and easy to understand method. You simply override the "isValid" method of Zend_Form (or Zend\Form).

/**
 * Overrides the parent class isValid method in order to support validating
 * that the passwordConfirm field is identical to the password field.
 *
 * @param  $data input data
 * @return bool
 */
public function isValid($data) {
    // validate that the value given for the 'passwordConfirm' field is
    // identical to the 'password' field
    $validator = new Zend_Validate_Identical($data['password']);
    $validator->setMessages(array(
        Zend_Validate_Identical::NOT_SAME      => 'Passwords do not match',
        Zend_Validate_Identical::MISSING_TOKEN => 'Passwords do not match'
    ));
    $this->getElement('passwordConfirm')->addValidator($validator);

    return parent::isValid($data);
}

You could of course attach more validators to other elements before calling "parent::isValid()" if you wish to do so.

wilmoore
+7  A: 

The current version of Zend_Validate has this built in - while there are plenty of other answers, it seems that all require passing a value to Zend_Validate_Identical. While that may have been needed at one point, you can now pass the name of another element.

From the Zend_Validate section of the reference guide:

Zend_Validate_Identical supports also the comparison of form elements. This can be done by using the element's name as token. See the following example:

$form->addElement('password', 'elementOne');
$form->addElement('password', 'elementTwo', array(
    'validators' => array(
        array('identical', false, array('token' => 'elementOne'))
    )
));

By using the elements name from the first element as token for the second element, the validator validates if the second element is equal with the first element. In the case your user does not enter two identical values, you will get an validation error.

Tim Lytle
Very nice solution, I am deleting my posted answer as it became dated now.
DavidHavl