– Part 4 Configuring Zend Validators
Welcome to the fourth and final part in the Zend Form Mastery with Zend Config series. Previously we looked at the basic form options, element and form wide prefixes, filters and element options. In this installment, we’re going to look at configuring Zend Validators via our XML config.
With the Zend Framework, there are 28 standard validators and as well as an additional sets when working with files. No matter what you want to do, at least initially, there will be a validator to suit your needs. To go in to all of them will take more time than is allowed in the confines of this article. So we’re going to work through 5 of the more interesting and likely used ones. These are:
Now you could say that there are other, more interesting, validators than these and that's true. But they serve to highlight an interesting set of use cases that you may come across when using Zend Form as well as getting you up to speed if you’re new to it.
Going back to the code that we’ve been using throughout the series, we’re going to add in elements to our form XML configuration file (/application/modules/forms/config/forms/form.xml) that will have a one to one relation with the five validators listed above.
But First - An Introduction
Before we go through the validators, I think it’s important to do more than to simply run through a hand-picked bunch. As the old saying goes, if you give a man a fish, you feed him for a day, if you teach a man to fish, you feed him for life.
So here’s the core concepts on implementing validators. When you’re going to implement a validator, open up the respective class. We’ll use Float as an example as it’s not too large and it’s not too small.
When you open the file, you’ll see a few key things:
- a set of class constants
- a protected array called _messageTemplates
- a protected variable _locale
This outlines for us what our options are when configuring it. Did you notice that the constant names match the keys of the _messageTemplates array? So what we can do here is override the value of the message templates and to specify a locale. To override a message template, we do so by taking the value of a class constant and using that as the key as we’ll see shortly. For locale, we can specify a valid locale for it to comply with.
As you look through each of the classes, you'll see similar functionality and it will start to become clearer what the options are that you can add and set for each validator configuration. But now, let's have a look at the 5 validators, starting with Email Address.
EmailAddress, as the name implies, is designed to validate an email address. The class, Zend_Validate_EmailAddress, can validate an email address based on:
- mx record
- local part
- dot atom
- quoted strong
You’ll find this in the constants at the top of the class. Given these validations, they have accompanying validation message templates. So what we’re going to do is configure the validator and allow it to test fairly simple email addresses. Have a look at the XML configuration sample below.
<validators> <email> <validator>EmailAddress</validator> <options> <messages> <emailAddressInvalid>The email address is invalid</emailAddressInvalid> </messages> </options> </email> </validators>
What we’ve done is to create a new validator, called ‘email’, and specified the EmailAddress validator with “EmailAddress”. We’ve then overridden the message template: “emailAddressInvalid” with a message of our own. So now when that message is encountered, the user will see “The email address is invalid” displayed in the errors list.
Now all we need to do is to enter an invalid email address in the form and the error will be thrown.
There are all kinds of post codes in the world. Have a look at the sample list below:
- SE16 5GN - England
- 4001 - Australia
- 90712 - Germany
But what if we are building a multi-lingual or multi-region form? What if we’re validating post codes for Germany, Austria, Switzerland or France?
Luckily for us, like a lot of the Zend Framework components, the validator library interacts with other modules, specifically the Zend Locale module. So what we’re going to do is to setup the validator and then specify a series of locales that it will validate against.
Have a look at the code below and let’s go through it.
<postCode> <validator>PostCode</validator> <options> <messages> <postcodeInvalid>A post code is required</postcodeInvalid> </messages> <locale>de_AT</locale> <format>AT_\d+</format> </options> </postCode>
What we’ve done is to set the locale as de_AT, or Austria and requested the respective format. Along with that, we’ve overridden the postcodeInvalid message template with our own, as in the EmailAddress validator earlier. Now, when a value is entered in the post code field, it will need to comply with Austrian format rules.
Now these ones have been rather trivial. But what if we needed to check a database for a record, say a username or city to see if it existed? What if people could say where they were from and for some reason, we only allowed one person from a specific city to enter.
Well, that’s quite simple with the Zend_Validate_DbNoRecordExists validator. In the code below, you’ll see that we’ve told it the table to refer to, the field to check within and we’ve, once again, overridden a message template value with one of our own.
<dbRecordNotExists> <validator>Db_NoRecordExists</validator> <options> <messages> <recordFound>That city exists</recordFound> </messages> <table>cities</table> <field>name</field> </options> </dbRecordNotExists>
We don’t need to specify a database adapter, so long as one is available within the existing environment. We need only specify a table and column, field, and a query similar to the following will be run when the form is submitted:
SELECT COUNT(*) FROM <table> WHERE <field> = <field_value>
If the value returned is equal to or greater than 1, then the validation fails as there’s a record there already. If it’s less than 1, then the validation succeeds. If you want the inverse to happen, use the Zend_Validate_DbRecordExists validator to ensure that a record must be there.
Iban is short for International Bank Account Number. According to Wikipedia, it is:
an international standard for identifying bank accounts across national borders with a minimal risk of propagating transcription errors.
So each Iban number needs to be unique to a country, sort of like the post code we validated earlier. So we’re going to setup a simple validator to do just this, and once again, our friend Zend Locale comes to the rescue.
<iban> <validator>Iban</validator> <options> <messages> <ibanNotSupported>That number is not supported</ibanNotSupported> </messages> <locale>de_DE</locale> </options> </iban>
You can see that we've set the locale to be Germany and we've overridden the ibanNotSupported message. Now we will have to enter a value that is of the following format: DEkk BBBB BBBB CCCC CCCC CC.
Where B is the Branch identifier and C is the Account No.
Now InArray is likely the simplest of the lot. All we’re doing there is to ensure that the value entered is in a safe list that we’ve pre-set. A good example of this is gender where the allowable values will be either Female or Male. So let’s have a look
<inarray> <validator>InArray</validator> <options> <messages> <notInArray>That value is not allowed</notInArray> </messages> <haystack> <male>Male</male> <female>Female</female> </haystack> </options> </inarray>
Like the in_array method in PHP itself, we’re looking for a key in a haystack. So we need to provide a haystack to look within. Then within that, we enter a list of values where the key is the value that will be sought and the value is the displayable value, like a select box. Now, when the user enters a value, it needs to be either Male or Female.
Ok, now that was a rapid run through of implementing validators in Zend Forms with Zend_Config. But you can see from each that really, all we need to do is a few simple things. These are:
- Set the name of the validator
- Set the validator to be used
- Override, if desired, one or more of the message templates
- Specify options that match the details provided in the class itself.
With that, we can now set any number of validators in our forms and save ourselves a lot of code and work validating forms and getting sanitised output.
What validators do you use? Could you configure them this way?