1

I am having a problem with the filtering and validation of the form below. If the two mobile numbers are entered in national format (07777654321) the form validation fails, but if they are entered in international format (447777654321) it validates. My understanding is that the filters will be applied first so when identical is applied both mobile and mobile_confirm should have been processed with the same set of filters.

So if I enter 07777654321 into both fields it will get filtered to 447777654321 in both fields which should then validate. Where am I going wrong.

I am using ZF 1.11.3.

<?php

class Test_Form_Check extends Zend_Form
{

    public function init()
    {

        $mobile= new Zend_Form_Element_Text( 'mobile' );
        $mobile->addFilter(new Test_Filter_MobileFilter('44'))
                ->addValidator(new Test_Validate_Mobile())
                ->setRequired( true );

        $mobile1= new Zend_Form_Element_Text( 'mobile_confirm' );
        $mobile1->addFilter(new Test_Filter_MobileFilter('44'))
                ->addValidator(new Test_Validate_Mobile())
                ->addValidator('Identical', false, array('token' => 'mobile', 'messages' => 'Mobile numbers do not match.'))
                ->setRequired( true );

        $Add = new Zend_Form_Element_Submit('Add');
        $Add->setLabel('Submit');

        $this->addElement($mobile)
                ->addElement($mobile1)
                ->addElement( $Add );

    }
}


class Test_Validate_Mobile extends Zend_Validate_Abstract
{
    const NOT_DIGITS   = 'notDigits';
    const STRING_EMPTY = 'digitsStringEmpty';
    const INVALID      = 'digitsInvalid';
    const INVALIDPHONE = 'phonenumberinvalid';

    protected static $_filter = null;

    protected $_messageTemplates = array(
        self::NOT_DIGITS   => "'%value%' must contain only digits",
        self::STRING_EMPTY => "'%value%' is an empty string",
        self::INVALID      => "Invalid type given. String, integer or float expected",
        self::INVALIDPHONE => "Invalid number, try with country code",
    );


    public function isValid($value)
    {
        if (!is_string($value) && !is_int($value) && !is_float($value)) {
            $this->_error(self::INVALID);
            return false;
        }

        if (!preg_match('/^(447)[0-9]{9}$/', $value)) {
            $this->_error(self::INVALIDPHONE);
            return false;
        }

        $this->_setValue((string) $value);

        if ('' === $this->_value) {
            $this->_error(self::STRING_EMPTY);
            return false;
        }

        if (null === self::$_filter) {
            require_once 'Zend/Filter/Digits.php';
            self::$_filter = new Zend_Filter_Digits();
        }

        if ($this->_value !== self::$_filter->filter($this->_value)) {
            $this->_error(self::NOT_DIGITS);
            return false;
        }

        return true;
    }
}


class Test_Filter_MobileFilter implements Zend_Filter_Interface
{
    /**
    * Default country code
    *
    * @var string
    */
    protected $_def_country = '44';

    public function __construct($options = null)
    {
        if ($options !== null) {
            if (is_string($options) && is_numeric($options)) {
                $this->_def_country = $options;
            }
            else {
                require_once 'Zend/Filter/Exception.php';
                throw new Zend_Filter_Exception('Options not valid country code');
            }
        }
    }

    public function filter($value)
    {
        if (!empty($value)) {
            $replace = array(' ','+','-','(',')');

            $value = str_replace($replace, '', $value);
            $value = preg_replace('/\A0/', $this->_def_country, $value);

        }
        return $value;
    }

}

I will be very grateful for any help with this. It is driving me round the bend.

2
  • So have you checked the filtering alone to see if after filtering you get the desired values? Commented Mar 30, 2012 at 12:03
  • Yes. The filtering works correctly, as far as I can tell. On failing validation the form is displayed again with national format changed to international format as expected. Commented Mar 30, 2012 at 12:07

1 Answer 1

3

I guess problem is with Zend_Validate_Identical validator , it uses unfiltered raw value from $_POST. Just quick fix:

class My_Validate_Identical extends Zend_Validate_Identical
{
    /**
     *
     * @var Zend_Form_Element 
     */
    protected $_element = null;

    public function __construct($token = null)
    {
        if (is_array($token) && array_key_exists('element', $token)) {
            $this->_element = $token['element'];
        }
        parent::__construct($token);
    }
    public function isValid($value, $context = null)
    {
        $context[$this->getToken()] = $this->_element->getValue();
        return parent::isValid($value, $context);
    }    
}

Attaching validator:

$mobile1->addValidator(new My_Validate_Identical(array(
                'token' => 'mobile', 
                'messages' => 'Mobile numbers do not match.',
                'element' => $mobile
                )))

Hope this helps :)

Sign up to request clarification or add additional context in comments.

2 Comments

I thought it must be something simple. Thank you so much for your help.
good that this helped, because you didn't provide error message, I was not sure if this was the case...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.