Adding automatic JavaScipt validators to CakePHP

I’m reposting the validators.php file that I uploaded in my previous post, but this time adding a function that will automatically generate a javascript function called validate() that returns an array of error strings. This is made possible because CakePHP’s validation model uses regular expressions.

NOTE: This function has been written using my modified validator class. Please read my previous post to see what it is all about.

The strings and expressions are identical to the ones you get by callling $this->modelName->validates() in a controller, so you can avoid a round trip to the server in many cases.

To use, drop the validators.php into your app helpers directory (as before), and call the function $validators->javascriptErrors(’modelName’); where modelName is the name of the model you want to pull the validation data from. For those of you playing at home, you may notice that the $modelNames variable gets converted to an array - this is because you can actually supply an array of modelNames if you need to validate the inputs from multiple models. Why? I had a need for it in a project, which I might go through later :)

Now, this isn’t quite complete, because it only returns an array of strings, you still need to output the string somehow. I usually output the strings to div, as I hate JavaScript alerts. The code for which is here. In that file I have defined a function called validateForm(form); which updates the div and returns false on an error, so you can use it in the onSubmit handler for the form.

Improved validation using CakePHP

I quite like CakePHP - in fact, I find it rather difficult to do site without it now. It makes everything so much easier, especially the ActiveModel classes. However, I have found the validation model a little lacking. The way it is currently implemented only allows one validation expression for each database column, and you need to re-write the validation message on each page the model is used on. This is quite restrictive and error prone - if you need to add a field to the database, you have to update more than one page.

I have managed to modify the way the validators work, so that you can define a message and have multiple validation expressions for each field.

I used the modifications on the AccountancyAge Careers Fair by modifying the model.php file that lives in the Cake library directory and it worked really well, but I wanted to set it up so that I didn’t have to modify these files everytime - It is really inconvienient to have to re-make the changes when updating the library. This is expecially a problem at the moment, because there seems to be a new release candidate every other day (Which is great - can’t wait for version 1!)

Anyway, after a little digging, I found that it is possible to override the app_model.php file in the same way as you can override the default app_controller.php file. By placing a copy of the file in the app/ directory, Cake will use this file instead.

The modification

The modification as it stands overrides the invalidFields function of model.php (this is based on RC3 - RC4 should work ok as well). You can download the new app_model.php here.

To define validation rules, you add an associative array with the paramaters expression and message. This is probably best explained using an example. Say you have a required field called “post_code” that must not be empty and must be 4 digits, you could do the following:

var $validate = array(

‘post_code’ => array(

array(’expression’ => VALID_NOT_EMPTY, ‘message’ => ‘You have not entered a post code’),
array(’expression’ => ‘/\d{4}/’, ‘message’ => ‘A postcode must be four digits’)

)
);

Easy as! There is one last thing though. To make it easier to display the messages, I have created the following user helper called validators.php (Drop it in to app/views/helpers) (Download validators.php here)

To use, you put the function < ?php echo $validators->tagErrorMessages() ?> (Don’t forget to include Validators in your helper array) which will generate a block message wrapped in div tags with the class “message”. You can customise this file if you don’t like the way it is displayed.

Happy baking :)