1. Data Validation

Creating custom validation rules can help to make sure the data in a Model conforms to the business rules of the application, such as passwords can only be eight characters long, user names can only have letters, etc.

The first step to data validation is creating the validation rules in the Model. To do that, use the Model::validate array in the Model definition, for example:

Example 10.1. /app/models/user.php

<?php
class User extends AppModel {
   var $validate = array(
      'login' => '/[a-z0-9\_\-]{3,}/i',
      'password' => VALID_NOT_EMPTY,
      'email' => VALID_EMAIL,
      'born' => VALID_NUMBER
   );
}
?>

Validations are defined using Perl-compatibile regular expressions, some of which are pre-defined in /libs/validators.php. These are:

VALID_NOT_EMPTY
VALID_NUMBER
VALID_EMAIL
VALID_YEAR

If there are any validations present in the model definition (i.e. in the $validate array), they will be parsed and checked during saves (i.e. in the Model::save() method). To validate the data directly use the Model::validates() (returns false if data is incorrect) and Model::invalidFields() (which returns an array of error messages).

But usually the data is implicit in the controller code. The following example demonstrates how to create a form-handling action:

Example 10.2. Form-handling Action in /app/models/blog_controller.php

<?php
class BlogController extends AppController {
   function add () {
      if (empty($this->params['data'])) {
         $this->render();
      }
      else {
         $this->post->set($this->params['data']);
 
         if ($this->post->save()) {
            $this->flash('Your post has been saved.','/blog');
         }
         else {
            $this->set('data', $this->params['data']);
            $this->validateErrors($this->post);
            $this->render();
         }
      }
   }
}
?>

The view used by this action can look like this:

Example 10.3. A Form in a View in /app/views/blog/add.thtml

<h2>Add post to blog</h2>
 
<?=$this->formTag('/blog/add')?>
 
<div class="blog_add">
<p>Title: <?= $html->inputTag('title', 40)?>
   <?=$this->tagErrorMsg('title', 'Title is required.')?></p>
<p><?=$this->areaTag('body') ?>
   <?=$this->tagErrorMsg('body', 'Body is required.')?></p>
 
<p><?=$this->submitTag('Save')?></p>
</div>
</form>

The Controller::validates($model[, $model...]) is used to check any custom validation added in the model. The Controller::validationErrors() method returns any error messages thrown in the model so they can be displayed by tagErrorMsg() in the view.