Why can't I override the default validation error message? - php

I'm using Zend_Validate to validate some form input (Zend Framework version is 1.8.2). For some reason, using the Zend_Filter_Input interface as described here does not work:
$data = $_POST;
$filters = array('*' => array('StringTrim'));
$validators = array('driverName' => array('NotEmpty','messages' => 'This should override the default message but does not!'));
$inputFilter = new Zend_Filter_Input($filters,$validators,$data);
$messages = $inputFilter->getMessages();
debug($messages); //show me the variable contents
Output from debug($messages):
Array
(
[driverName] => Array
(
[isEmpty] => You must give a non-empty value for field 'driverName'
)
)
No matter what I do, I cannot override that message. If I use the validator directly, i.e.:
$notEmpty = new Zend_Validate_NotEmpty();
$notEmpty->setMessage('This WILL override the default validation error message');
if (!$notEmpty->isValid($_POST['driverName'])) {
$messages = $notEmpty->getMessages();
debug($messages);
}
Output from debug($messages):
Array
(
[isEmpty] => Please enter your name
)
Bottom line. I can get validators to work, but without the benefits of the Zend_Filter_Input interface method of validation I might as well write my own validation class!
Does anyone have a clue as to why this is happening, and how to fix it?
Could it be a bug?

The messages key in the validator array must be passed an array of key/value pairs, where the key is the validation message constant, and the value is your custom error message. Here's an example:
$validators = array(
'excerpt' => array(
'allowEmpty' => true,
array('StringLength', 0, Ctrl::getOption('blog/excerpt/length')),
'messages' => array(Zend_Validate_StringLength::TOO_LONG => 'The post excerpt must not exceed '.Ctrl::getOption('blog/excerpt/length').' characters.')
),
);
However, in your case, the error message you are receiving is coming from the the allowEmpty meta command of Zend_Filter_Input. This isn't really a standard validator. You can set it like so:
$options = array(
'notEmptyMessage' => "A non-empty value is required for field '%field%'"
);
$input = new Zend_Filter_Input($filters, $validators, $data, $options);
// alternative method:
$input = new Zend_Filter_Input($filters, $validators, $data);
$input->setOptions($options);
If you need a different not empty message per field, I'd recommend setting allowEmpty => true and adding a NotEmpty validator with a custom message.
For your reference, the correct message key for the NotEmpty validator is Zend_Validate_NotEmpty::IS_EMPTY

The MESSAGES argument takes an array, not a string. Try this:
$validators = array('driverName' =>
array('NotEmpty',
'messages' => array(
0 => 'This should override the default message but does not!'
)
)
);

It's a bug, it's in the JIRA of Zend Framework...

Related

CakePHP validation error on an optional field

I'm creating a form in CakePHP, where there is a field that is output only on certain conditions. However, when it is not output, validation invalidates it. I'm not sure where I did wrong?
Validation in Model:
public $validate = array(
'extra_requirement_ok' => array(
'notEmpty' => array(
'rule' => array('comparison', '!=', 0),
//'required' => false,
'message' => 'Must'
),
),
);
The input in the view:
if ($check) {
echo $this->Form->input('extra_requirement_ok');
}
EDITED:
When I check the data that is passed when is submitted, array key for extra_requirement_ok does not exist. But I created a custom validation and check the array that is passed to the custom validation function, it returns extra_requirement_ok = '0'. What gives?
I figured this out.
I set 0 as defined value in the database, as the data is being saved, 0 is generated by default and that triggered validation. Now the database column is set to NULL and it's fine now.

Db_NoRecordExists error message is overwrite by ->addErrorMessage()

My Db_NoRecordExists message is overwite by addErrorMessage.
Code:
$emailaddress = new Zend_Form_Element_Text('EmailAddress');
$emailaddress->setRequired(true)
->setAttrib('size', '30')
->addFilters(array('StringTrim', 'StripTags'))
->addValidator('EmailAddress',TRUE)
->setDecorators($decorators)
->addErrorMessage('Please Enter Va`enter code here`lid Values.')
->setAttrib('MaxLength',100)
->setAttrib('onkeyup','setUserName()')
->setAttrib('onkeypress','setUserName()')
->setAttrib('onfocus','setUserName()')
->setAttrib('onchange','setUserName()')
->setAttrib('Maxlength', '100');
$emailaddress ->class="textbox";
and
public function isValid($data)
{
$this->getElement('EmailAddress')
->addValidator('Db_NoRecordExists', false, array(
'table'=>'puntermaster',
'field' => 'EmailAddress',
'messages' => array(Zend_Validate_Db_Abstract::ERROR_RECORD_FOUND => 'A user with email address already exists'),
'exclude' => array( 'field' => 'Sno', 'value' => $data['Sno'])
), TRUE);
return parent::isValid($data);
}
If you add a custom error message to your form element using addErrorMessage() or addErrorMessages() and one of the validators fails validation, then the custom error message will be used instead of the validator specific error message.
Only use addErrorMessage if you want to override all of the validator's error messages for a form element.
Another use of addErrorMessage is to call it after you've validated the form element and you want to add a custom message you later retrieve with getErrorMessages().

Displaying Form Error Messages from Array

I wanted to incorporate GUMP https://github.com/Wixel/GUMP into my site for server side validation. But unfortunately the documentation is light and I am new to PHP.
Here is my validation code:
//Validation
$gump = new GUMP();
$rules = array(
'dept' => 'required|numeric',
'hosp' => 'required|numeric',
'subhosp' => 'required|numeric',
'user' => 'required|numeric',
'gpo' => 'required|boolean|exact_len,1',
'clin' => 'required|valid_name',
'clinmail' => 'required|valid_email',
'comp' => 'required|alpha_dash',
'cpt' => 'required|alpha_dash',
'past' => 'required|boolean|exact_len,1',
'latex' => 'required|boolean|exact_len,1',
);
$validated = $gump->validate($_POST,$rules);
print_r($validated); // Something went wrong
The output from the above code gives me an array like so when I am looking at my AJAX response in FireBug:
Array
(
[0] => Array
(
[field] => clin
[value] => .-0
[rule] => validate_valid_name
)
[1] => Array
(
[field] => clinmail
[value] => %$sd
[rule] => validate_valid_email
)
)
And I what I need is something like so:
<div class="error-msg">You did not enter a valid email address</div><br>
<div class="error-msg">You did not enter a valid username</div><br>
From the documentation I get:
if($validated === TRUE)
{
// Do something, everything went well
}
else
{
// This is where I am stuck. Do I have to loop through and put my <div> tags here?
}
My question is how would the community handle outputting error messages with this class? My only thought is that I loop through the results above and output different messages depending on the field and the rule that was broken but that seems tedious. Is there a better way or a better class to use that does standalone PHP input validation? I was using another very easy to use class but it started breaking when I moved away from inline PHP to AJAX.
edit your code to:
$gump = new GUMP();
$rules = array(
'dept' => 'required|numeric',
'hosp' => 'required|numeric',
'subhosp' => 'required|numeric',
'user' => 'required|numeric',
'gpo' => 'required|boolean|exact_len,1',
'clin' => 'required|valid_name',
'clinmail' => 'required|valid_email',
'comp' => 'required|alpha_dash',
'cpt' => 'required|alpha_dash',
'past' => 'required|boolean|exact_len,1',
'latex' => 'required|boolean|exact_len,1',
);
$error_texts = array(
'dept' => 'You must enter a numeric value',
'hosp' => 'You must enter a numeric value',
'subhosp' => 'You must enter a numeric value',
'user' => 'You must enter a numeric value',
'gpo' => 'You must enter a boolean value',
'clin' => 'You must enter a valid name',
'clinmail' => 'You must enter a valid email',
'comp' => 'You must enter a valid alpha dash',
'cpt' => 'You must enter a valid alpha dash',
'past' => 'You must enter 1 char',
'latex' => 'You must enter 1 char',
);
$validated = $gump->validate($_POST,$rules);
if($validated === TRUE)
{
echo "Every thing is ok";
}
else
{
foreach($validated as $key=>$error)
{
echo '<div class="error-msg">' . $error_texts["{$error['field']}"] . '</div><br />';
}
}
I would like to add that if a validation fails twice, for example if a value is required and has to exist out of more than 10 characters then #semsems answer would print multiple lines for the same field.
I changed the above code and added:
$_validated = array();
foreach($validated as $key=>$error)
{
if ( !in_array($error['field'], $_validated) )
{
print '<div class="error-msg">' . $error_texts["{$error['field']}"] . '</div>';
$_validated[] = $error['field'];
}
}
I know this question is a year old and been answered, but since I based myself on the accepted answer and in my view made it a sweet better (completely generic with locale as extra), I thought it would be nice to share and get some feedback... what do you guys think about my code? Now based on semsem's answer... I like the way he coded part of it and I derived from it to come up with the following code:
First I extended GUMP with my own class so I could overwrite some functions
<?php
require("gump.class.php");
class GumpValidator extends GUMP
{
private $locale;
private $translator;
public function GumpValidator($lang = "en")
{
$this->locale = $lang;
$this->loadValidationLocales();
}
/** Overwrite the default validate() function of GUMP so that I can add an extra "message" property */
public function validate(array $input, array $ruleset)
{
$validated_data = GUMP::validate($input, $ruleset);
if(is_array($validated_data)) {
foreach($validated_data as $index=>$error) {
$validation = str_replace(":attribute", $error['field'], $this->translator[$error['rule']]);
$validation = str_replace(":param", $error['param'], $validation);
$validated_data[$index++]['message'] = $validation;
}
}
return $validated_data;
}
/** Depending on the language locale, load the proper set of validation messages */
private function loadValidationLocales()
{
$this->translator = require "/lang/" . $this->locale . "/validation.php";
return $this->translator;
}
} // EOC
Then as you can see from the extended class, I created myself a set of locale language message for validation and I took the full list of possible validation errors directly from the GUMP code on Github, take a look at the function get_readable_errors() to get the full list of errors. Github link here... The locales which I created are saved under separate language folders /lang/en/validation.php, /lang/fr/validation.php, etc... You can easily create as many as you want... I took the concept from Laravel Framework... These validation.php files looks for example, like this (1 file per language/locale), here is the English one:
<?php
return array(
"validate_alpha" => "The :attribute may only contain letters.",
"validate_alpha_numeric" => "The :attribute may only contain letters and numbers.",
.....
);
Then finally in my POST to validate code I just call it like this:
// load my extended class with language locale I want to use
$gump = new GumpValidator("en");
// now validate the data
$validated_data = $gump->validate( $_POST, $rules );
So at the end I get the extra property of message inside the $validated_data object returned with the option of whichever locale language I chose to display the error message...and voilĂ !!! In my case I read the code in javascript to display the errors in Bootstrap alert, but if you want PHP you can look at semsem answer as well. So at the end, I know it takes more code since I have an extra class to wrap it and extra locales, but isn't sweet to first have it generic (per validation errors) and second to have multiple locale language easily?

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