Zend Framework - integer validator - php

Zend Framework seems to have a feature for validating integers (checked the /Validate/Int.php in the library for the purpose) which validates correctly float numbers as integer, while I want to show error when float number is given.
Here is a snippet from my form:
$form['my_int'] = new Zend_Form_Element_Text('my_int');
$form['my_int']->setLabel('My Int')
->setRequired(true)
->addFilter('StringTrim')
->addDecorator('Errors', array('placement'=>'prepend',
'class'=>'my-err'))
->addValidator('NotEmpty', true, array('messages' =>
array('isEmpty' => 'Please provide data')))
->addValidator('int', true, array(
'locale' => 'en_US',
'messages' => array(
'intInvalid' => 'Please provide valid data',
'notInt' => 'Please provide valid data'
)
));
So when I provide something different from string, integer or float, 'intInvalid' error is triggered and my custom message is shown. When float number like 1.23 is provided 'notInt' error is shown. The problem is when you provide e.g. 1.00, then the validator checks for "!Zend_Locale_Format::isInteger($value, array('locale' => $this->_locale))" and decides the input is integer and when you try to add float number in the the database in an integer field, you get error.
How should I organize my form validation so that when float number is provided, no matter what, to show error to the user?

You should add the Int filter to that element.
$element->addFilter(new Zend_Filter_Int());

Related

CakePHP3: validate decimal input

This is probably a trivial question, but I can't figure it out.
I want my price value to have 2 decimal places. CakePHP should validate this, but it doesn't. CakePHP only checks if the input is a number and doesn't allow to pass decimal values.
I want it to check and pass values like 2.22 but also 2. Now it only allows the latter.
Part of validationDefault method:
$validator
->decimal('price')
->allowEmpty('price');
I checked CakePHP API and found decimal() method description:
decimal( float $check , integer|null $places null , string|null $regex null )
Checks that a value is a valid decimal. Both the sign and exponent are
optional.
But it does not take string as a parameter in this context(and CakePHP assign decimal() to my price column automatically during baking), so I guess this is why decimal('price', 2) don't work.
Any ideas?
REQUESTED EDIT:
Whole validationDefault method:
public function validationDefault(Validator $validator)
{
//$validator for other columns
$validator
->allowEmpty('price')
->add('price', 'money', array('rule' =>
array('money', 'left'),
'message' => 'Please supply a valid monetary amount.'));
return $validator;
}
My input field is created using HTML helper.
You should use money to validate price
$validator->notEmpty('price',array('message' => 'Please provide your amount'))
->add('price', 'money', array('rule' => array('money','left'),
'message' => 'Please supply a valid monetary amount.'));
Your can also try this
$validator->notEmpty('amount',array('message' => 'Please provide your amount'))
->add('amount','numeric',array('rule' => 'numeric' ,'message'=> 'Please provide a valid amount'));

Change validation rules on the fly

I'm working on a form that contains user data, specifically a phone number field. The phone number typically isn't required so the only validation rule in the model is the usphone rule. However, if the user is submitting this form, the phone number becomes necessary. I thought I'd be able to simply add a validate rule on the fly, set the model and call the validates method, but either I'm doing it wrong or it's not working the way I expected.
In my controller:
# Update a few validation rules that are specific to this context
$this->Proposal->Requestor->validate['phone_number']['notempty'] = array(
'rule' => 'notEmpty',
'message' => 'Please enter a phone number so can can contact you with any questions about the work.',
'allowEmpty' => false,
'required' => true,
);
$validationErrors = array();
$this->Proposal->Requestor->set( $this->data['Requestor'] ); # $this->data['Requestor']['phone_number'] only (no other requestor data)
if( !$this->Proposal->Requestor->validates( array( 'fieldList' => array( 'phone_number' ) ) ) ) {
$validationErrors['Requestor'] = $this->Proposal->Requestor->validationErrors;
}
No errors are reported, even if I leave the phone number field empty. In this case, the only information I'm requesting from the user is their phone number, so the rest of the Requestor data is empty, but I've tried merging in the rest of the user data and I get the same result. If I remove the fieldList option, I get an error on a different field, but still nothing on the empty phone number.
Any idea what I'm missing here? I've been monkeying around with this for hours now and I just haven't found the right answer.
Thanks.
The solution ended up being twofold:
I had existing rule on the phone_number field that forced the value to be a US phone number. That rule also set allowEmpty to true and required to false. I wanted to catch an empty value so I could display a particularly precise message.
I had to update the existing rule to flip the allowEmpty and required values and also add a new rule with its last value set to true.
The final change, added in my controller action looks like this:
$this->Proposal->Requestor->validate = Set::merge(
$this->Proposal->Requestor->validate,
array(
'phone_number' => array(
'notempty' => array(
'rule' => 'notEmpty',
'message' => 'Please enter a phone number so can can contact you with any questions about the work.',
'allowEmpty' => false,
'required' => true,
'last' => true,
),
'usphone' => array(
'allowEmpty' => false,
'required' => true,
),
)
)
);
I can't remember whether I verified that the change to the existing usphone rule was strictly necessary given the last value of the new rule, but this combination is working fine.
You could try using the Multivalidatable Behaviour - http://bakery.cakephp.org/articles/dardosordi/2008/07/29/multivalidatablebehavior-using-many-validation-rulesets-per-model

AllowEmpty vs NotEmpty

New to CakePHP here - I'm going through the documentation on the site, trying to muster up some basic data validation for a model I'm creating. This will likely be the first of many questions I have about CakePHP.
In the CakePHP Book, the validation rules seem to specify two different methods for making sure that a field isn't empty - AllowEmpty, and NotEmpty.
Question - is there a tangible difference between these two? CakePHP states that validation rules should occur in your model or controller - is one better suited for a model, and the other for a controller? The Book doesn't say anything about this. I'm guessing that one is an older method that's simply still around?
What gives? Should I use a specific one, or both, or does it not matter?
Edit: I decided to check the CakePHP 1.3 class documentation for it (to check the default value of the allowEmpty attribute), but it doesn't even show up. It's not in the source code either...is there something I'm missing?
Welcome to Cake. I hope you enjoy it.
This is definitely one of the stranger aspects of Cake.
notEmpty is a rule in and of itself. You can define it in your $validation attribute. You can assign a message for when this validation fails. You can treat this as if it is any other validation rule.
allowEmpty is an option of another validation rule, normally not notEmpty. It is not a validation rule in-and-of-itself. This would allow, for example, you to define that a varchar field allows an empty string, '', or a string with no more than 20 characters.
Edit:
Here's some code
// model validation using 'notEmpty'
$validation = array(
'fieldName' => array(
'notEmpty' => array(
'rule' => 'notEmpty',
'message' => 'This value may not be left empty!'
),
... // other rules can go here
),
... // other fieldName can go here
);
// model validation using 'allowEmpty' to create an optional field
$validation = array(
'fieldName' => array(
'maxLength' => array(
'rule' => array('maxLength', 20),
'message' => 'This field may only contain 20 characters!',
'allowEmpty' => true // we'll also accept an empty string
),
... // other rules can go here
)
... // other fieldName can go here
);
I found a case where I had to use 'allowEmpty' => false instead of rule => 'notEmpty'. I had a form with an upload input (type='file') that had a validation rule of notEmpty, and it kept failing validation, even though the debugger showed the file[] array loaded. When I removed the 'notEmpty' rule and set allowEmpty => false, it worked, throwing an error when no file was chosen and accepting it when one was selected.
It must have something to do with the value being an array rather than a text value.
Its very simply to make server side validation in cakephp
Here is code for both validation (noEmpty, maxlength) for the same field.
'fieldName' => array(
'rule' => array('maxLength', 20),
'message' => 'fieldName should be less than 20 characters',
'allowEmpty' => true
),
'fieldName' => array(
'notEmpty' => array(
'rule' => array('notEmpty'),
'message' => 'Please enter field name',
),
),

How can I customise Zend_Form regex error messages?

I have the following code:
$postcode = $form->createElement('text', 'postcode');
$postcode->setLabel('Post code:');
$postcode->addValidator('regex', false,
array('/^[a-z]{1,3}[0-9]{1,3} ?[0-9]{1,3}[a-z]{1,3}$/i'));
$postcode->addFilters(array('StringToUpper'));
$postcode->setRequired(true);
It creates an input field in a form and sets a regex validation rule and works just fine.
The problem is that the error message it displays when a user enters an invalid postcode is this:
'POSTCODE' does not match against pattern
'/^[a-z]{1,3}[0-9]{1,3} ?[0-9]{1,3}[a-z]{1,3}$/i'
(where input was POSTCODE)
How can I change this message to be a little more friendly?
I think to remember, you can set the error message in the Validator:
$postcode = $form->createElement('text', 'postcode');
$postcode->setLabel('Post code:');
$postcode->addValidator('regex', false, array(
'pattern' => '/^[a-z]{1,3}[0-9]{1,3} ?[0-9]{1,3}[a-z]{1,3}$/i')
'messages' => array(
'regexInvalid' => "Invalid type given, value should be string, integer or float",
'regexNotMatch' => "'%value%' does not match against pattern '%pattern%'",
'regexErrorous' => "There was an internal error while using the pattern '%pattern%'"
)
);
$postcode->addFilters(array('StringToUpper'));
$postcode->setRequired(true);
If that doesn't work, try
setErrorMessages(array $messages): add multiple error messages to display on form validation errors, overwriting all previously set error messages.
If you define your validator as external variable use setMessage():
$validator = new Zend_Validate_Alnum();
$validator->setMessage('My custom error message for given validation rule',
Zend_Validate_Alnum::INVALID);
$formElement->addValidator($validator);
As you see in example above validator for form doesn't differ from any other kind of Zend_Validate_* instances.
Setting up validation messages involves looking into API Docs and finding out message constant for a given validation error (as I did in case of Zend_Validate_Alnum::INVALID). Of course if your IDE provides good context auto-completion just typing the validator class can be enough - as message constants are really self-explanatory in most cases.
Another way would be to use Zend_Form's magic methods, and simply passing 'messages' key, as a parameter to your validator:
$formElement->addValidator(array(
'alnum', false, array('messages' => array(
Zend_Validate_Alnum::INVALID => 'my message'
))
));
This would internally trigger the setMessages() method defined in Zend_Validate_Abstract, and in essence just a short-cut/time-saver defined for Zend_Form's.
NB: There's a dedicated section in ZF Manual regarding validation messages.
You could use the original Zend postcode validator
$user->addElement('text', 'postcode', array('label' => 'Postcode *',
'required' => true,
'class' => 'postcode_anywhere',
"validators" => array(
array("NotEmpty", false, array("messages" => array("isEmpty" => "Required *"),)),
array('PostCode', false, array('locale' => 'en_GB')
)
),
'filters' => array(array('StringToUpper')),
'class' => 'text'
)
);

Access custom error messages for InArray validator when using Zend_Form_Element_Select

I'm using Zend Framework 1.62 (becuase we are deploying the finished product to a Red Hat instance, which doesn't have a hgih enough PHP version to support > ZF1.62).
When creating a Form using Zend Form, I add a select element, add some multi options.
I use the Zend Form as an in-object validation layer, passing an objects values through it and using the isValid method to determine if all the values fall within normal parameters.
Zend_Form_Element_Select works exactly as expected, showing invalid if any other value is input other than one of the multi select options I added.
The problem comes when I want to display the form at some point, I cant edit the error message created by the pre registered 'InArray' validator added automatically by ZF. I know I can disable this behaviour, but it works great apart from the error messages. I've tryed the following:
$this->getElement('country')->getValidator('InArray')->setMessage('The country is not in the approved lists of countries');
// Doesn't work at all.
$this->getElement('country')->setErrorMessage('The country is not in the approved lists of countries');
// Causes a conflict elswhere in the application and doesnt allow granular control of error messages.
Anyone have any ideas?
Ben
I usually set validators as per my example below:
$this->addElement('text', 'employee_email', array(
'filters' => array('StringTrim'),
'validators' => array(
array('Db_NoRecordExists', false, array(
'employees',
'employee_email',
'messages' => array(Zend_Validate_Db_Abstract::ERROR_RECORD_FOUND => 'A user with email address %value% already exists')
))
),
'label' => 'Email address',
'required' => true,
));
The validators array in the element options can take a validator name (string) or an array.
When an array is passed, the first value is the name, and the third is an array of options for the validator. You can specify a key messages with custom messages for your element in this array of options.
If your using Zend_Form_Element_Select (or any of the Multi subclasses), on validation the InArray validator will only be automatically added if there is not one present.
You can set a validator as so:
$options = array(...);
$this->addElement('select', 'agree', array(
'validators' => array(
array('InArray', true, array(
'messages' => array(
Zend_Validate_InArray::NOT_IN_ARRAY => 'Custom message here',
),
'haystack' => array_keys($options),
)),
'multiOptions' => $options,
));
and then your validator will be used instead of the automatically attached one.
$el = $this->addElement($name, $label, $require, 'select');
$validator = new Zend_Validate_InArray(array_keys(AZend_Geo::getStatesList()));
$validator->setMessage('Invalid US State.');
$el
->setMultiOptions(AZend_Geo::getStatesList())
->setRegisterInArrayValidator(false)
->addValidator($validator)
->addFilter(new Zend_Filter_StringToUpper())
->addFilter(new T3LeadBody_Filter_SetNull())
->setDescription('US State. 2 char.');

Categories