Zend_Form
which is a Zend_Form_Element
as invalid, showing one or more custom error messages? The problem is mainly caused by the native counter-intuitive methods of the Zend_Form_Element
class which I’ll explain in more details. (Note the problem and the solution discussed here is valid for Zend Framework version 1.12 and below.)
Key Takeaways
- When creating a non-English website or application based on Zend Framework, developers often struggle with marking a field of a Zend_Form, which is a Zend_Form_Element, as invalid and displaying custom error messages. This is mainly due to the native counter-intuitive methods of the Zend_Form_Element class.
- The default behavior of the Zend Framework, owned by American company Zend, is to display error messages in English for every validator broken by user input. Developers can either translate every error message of the framework or explain in one or more messages that the input is invalid and show suggestions to insert an accepted value. The latter option is less complicated, especially for small and medium-sized projects.
- The solution to this problem lies in the creation of the field inside the form (init() method) and the use of the setErrorMessages() method in conjunction with a property of the validators of Zend Framework called breakChainOnFailure(). This property allows the validation process to stop at the first failed condition. This approach allows the form to show only the custom message when there’s invalid input.
Developing an Example
Let’s say that you have a form with different fields and take into account just one of them, for example an text input field used to let a user enter his name. The validators that you can use are different, but for the sake of example we’ll limit the length of the name and it’ll only allow alphabetic characters and spaces. Speaking the Zend Framework language, we’ll use theZend_Validate_StringLength
and the Zend_Validate_Alpha
classes respectively.
As you may already know, Zend Framework is owned by the American company Zend and so all of the messages it shows are in English. The default behavior of the framework is to display one or more error messages for every validator broken by the user input. So, for those who are building a non-English website, there are two options to have messages readable by all users: translate every error message of the framework, or explain in one or more messages that the input is invalid and show suggestions to insert an accepted value. The first option is over-complicated, especially for small and medium-sized projects, so I’ll show how to use the second option.
To keep it easy, we will set a single custom message: “The input is invalid. The value must have only alphabetic characters and spaces and its length must be between 3 and 50 characters.”
The Code
I’ll show the code that we’ll use during the article. First, this is the form that contains the input field for the name and the validators needed to check the data.<?php
class Application_Form_User extends Zend_Form
{
public function init() {
// create the field
$element = new Zend_Form_Element_Text("name");
$element->setLabel("Name");
// set the validators
$element->setValidators(array(
new Zend_Validate_Alpha(true),
new Zend_Validate_StringLength(
array("min" => 3, "max" => 50))
));
$element->setRequired();
// add the element to the form
$this->addElement($element);
// add a submit button
$element = new Zend_Form_Element_Submit("submit");
$element->setLabel("Submit");
$this->addElement($element);
}
}
In the controller we’ll check if the field is valid and act accordingly. Usually you won’t use the IndexController
and probably you have this validation in a specific controller. Anyway, to simplify the example, I’ll use it.
<?php
class IndexController extends Zend_Controller_Action
{
public function init() {
}
public function indexAction() {
$form = new Application_Form_User();
if ($this->getRequest()->isPost() &&
$form->isValid($this->getRequest()->getPost())) {
$this->view->message = "Valid input";
}
else {
$this->view->form = $form;
}
}
}
The view used is quite simple; it only shows the message and the form.
<?php
if (isset($this->message)) {
echo $this->message;
}
if (isset($this->form)) {
echo $this->form;
}
The source code above, without any CSS rule, will render as such:
Moreover, if you insert the invalid value “88” in the Name field you’ll see the messages:
Analyzing the Framework’s Methods
A good question to ask is if there are already methods available to face this kind of situation. The answer is almost . I mean there are methods, but they don’t always work as you expect (at least as I expect). The methods to manage the error messages are:setErrors(array $messages)
setErrorMessages(array $messages)
setErrors()
has only one parameter which is an array and uses its elements as messages to show in case of invalid input. An example of its use is:
<?php
// set the custom message in the case of an error
$element->setErrors(array("The input is invalid. The value must have only alphabetic characters and spaces and its length must be between 3 and 50 characters."));
This method, as well as displaying the given string(s), also marks the field as invalid.
It can be used at two times in the application logic, but in both it has a behavior which is not useful for our goal. The first is during the creation of the form element (init()
method). In this case the message is shown when the form has been loaded and before the user has inserted any data. Quite unpleasant. In this case the relevant part of code changes like this:
<?php
// set the validators
$element->setValidators(array(
new Zend_Validate_Alpha(true),
new Zend_Validate_StringLength(
array("min" => 3, "max" => 50))
));
$element->setRequired();
// set the custom message in the case of an error
$element->setErrors(array("The input is invalid. The value must have only alphabetic characters and spaces and its length must be between 3 and 50 characters."));
The second time occurs after the information has been sent during the usual data validation within the controller. What happens is that the custom message is appended to the default ones when an error occurs. In this case, the indexAction()
of the IndexController
changes in this way:
<?php
public function indexAction() {
$form = new Application_Form_User();
if ($this->getRequest()->isPost()) {
// If the input of the user is valid, set the success
// message. Otherwise, set the custom errors and show
// the form again.
if ($form->isValid($this->getRequest()->getPost())) {
$this->view->message = "Valid input";
}
else {
$form->getElement("name")->setErrors(array("The input is invalid. The value must have only alphabetic characters and spaces and its length must be between 3 and 50 characters."));
$this->view->form = $form;
}
}
else {
$this->view->form = $form;
}
}
Just like setErrors()
, the setErrorMessages()
method take as a parameter an array of strings which will be shown to the user in case of invalid input. An example of its use is:
<?php
$element->setErrorMessages(array("The input is invalid. The value must have only alphabetic characters and spaces and its length must be between 3 and 50 characters."));
This line of code still doesn’t solve the problem beucase it will either show the same error message for every not-satisfied condition or it will have no effect. If the line shown is used in the init()
method, in the same way shown for the setErrors()
, in case of error, the custom message will be shown as many times as the number of conditions violated by the user input. If the line is inserted during the usual data validation within the controller, in the same way explained before, there will be no effect. This means that the custom message won’t be displayed and the framework will show only the default messages.
Uncovering the Solution
Now the point is to understand when and how to insert the custom message so that the user can have a comparison and a suggestion about what values are accepted. Definitely, the when lies in the creation of the field inside the form (init()
method) and the how is due to the union of the setErrorMessages()
method and the use of a property of the validators of Zend Framework called breakChainOnFailure()
. The latter allows us to stop the validation process at the first failed condition. If we set up five validators but the first of them fails, the other four won’t be used.
To employ this property making use of the smallest possible number of code lines, I’ll change a little bit the code I have illustrated at the beginning. I’ll add to the init()
method the code line which uses the setErrorMessages()
method, and I’ll take advantage of one of the possible input configurations accepted by setValidators()
which expects an array of arrays. The array contained in the main one can have a maximum of three parameters, which are:
- A string (mandatory) to specify the validator to user.
- A boolean (optional, by default its value is
false
) to specify if the framework has to break the validation at the first failure or not. Thus, this parameter sets the value of the propertybreakChainOnFailure
which is what will help us in achieve our goal. - An array of options (optional, by default an empty array) different for every choosen validator
<?php
class Application_Form_User extends Zend_Form
{
public function init() {
// create the field
$element = new Zend_Form_Element_Text("name");
$element->setLabel("Name");
// set the validators
$element->setValidators(array(
array("Alpha", true, array("allowWhiteSpace" => true)),
array("StringLength", true, array(
"min" => 3, "max" => 50))
));
$element->setRequired();
// set the custom message in the case of an error
$element->setErrorMessages(array("The input is invalid. The value must have only alphabetic characters and spaces and its length must be between 3 and 50 characters."));
// add the element to the form
$this->addElement($element);
// add a submit button
$element = new Zend_Form_Element_Submit("submit");
$element->setLabel("Submit");
$this->addElement($element);
}
}
Conclusion
Using the code above, the form will show only the custom message when there’s invalid input… exactly what we wanted! In case you need to use more messages, for example suggestions in several stages, just add more strings to the array used for thesetErrorMessages()
method.
Image via Fotolia
Frequently Asked Questions (FAQs) on Setting Custom Error Messages for Zend Form Element
How can I customize the error message for a specific form element in Zend?
Customizing the error message for a specific form element in Zend is quite straightforward. You can use the setMessage()
method to set a custom error message for a specific validator. For instance, if you have a form element named ’email’ and you want to set a custom error message for it, you can do so as follows:$email = new Zend_Form_Element_Text('email');
$email->setLabel('Email Address')
->addValidator('NotEmpty', true)
->addValidator('EmailAddress');
$email->getValidator('NotEmpty')->setMessage('Please enter your email address');
In this example, the setMessage()
method is used to set a custom error message for the ‘NotEmpty’ validator of the ’email’ form element.
How can I set multiple custom error messages for a form element in Zend?
If you want to set multiple custom error messages for a form element in Zend, you can use the setMessages()
method. This method accepts an array of error messages. Here’s an example:$email = new Zend_Form_Element_Text('email');
$email->setLabel('Email Address')
->addValidator('NotEmpty', true)
->addValidator('EmailAddress');
$email->getValidator('NotEmpty')->setMessages(array(
Zend_Validate_NotEmpty::IS_EMPTY => 'Please enter your email address',
Zend_Validate_EmailAddress::INVALID => 'Please enter a valid email address'
));
In this example, the setMessages()
method is used to set multiple custom error messages for the ‘NotEmpty’ validator of the ’email’ form element.
How can I display a custom error message when a form fails validation in Zend?
When a form fails validation in Zend, you can display a custom error message by using the addError()
method. This method adds an error message that will be displayed when the form fails validation. Here’s an example:$form = new Zend_Form();
$form->addElement('text', 'email', array(
'validators' => array(
array('validator' => 'NotEmpty', 'options' => array('messages' => 'Email is required')),
array('validator' => 'EmailAddress', 'options' => array('messages' => 'Invalid email address'))
)
));
if (!$form->isValid($_POST)) {
$form->addError('There were errors in your submission. Please correct them and try again.');
}
In this example, the addError()
method is used to add a custom error message that will be displayed when the form fails validation.
How can I change the default error messages in Zend?
You can change the default error messages in Zend by using the setMessage()
method. This method allows you to set a custom error message for a specific validator. Here’s an example:$email = new Zend_Form_Element_Text('email');
$email->setLabel('Email Address')
->addValidator('NotEmpty', true)
->addValidator('EmailAddress');
$email->getValidator('NotEmpty')->setMessage('Please enter your email address');
$email->getValidator('EmailAddress')->setMessage('Please enter a valid email address');
In this example, the setMessage()
method is used to change the default error messages for the ‘NotEmpty’ and ‘EmailAddress’ validators of the ’email’ form element.
How can I set a custom error message for a form element that is required in Zend?
If a form element is required in Zend, you can set a custom error message for it by using the setRequired()
and addErrorMessage()
methods. Here’s an example:$email = new Zend_Form_Element_Text('email');
$email->setLabel('Email Address')
->setRequired(true)
->addErrorMessage('Email is required');
In this example, the setRequired()
method is used to make the ’email’ form element required, and the addErrorMessage()
method is used to set a custom error message for it.
I'm a (full-stack) web and app developer with more than 5 years' experience programming for the web using HTML, CSS, Sass, JavaScript, and PHP. I'm an expert of JavaScript and HTML5 APIs but my interests include web security, accessibility, performance, and SEO. I'm also a regular writer for several networks, speaker, and author of the books jQuery in Action, third edition and Instant jQuery Selectors.