Saturday, October 17, 2009

Google Maps car on my street.

And this how it really looks like….

IMG_5418 IMG_5419

Wednesday, October 14, 2009

CakePHP 1.2 - dynamical validation rules.

Many times we need to use one model in many forms with different validation rules. This is not only the case when we have a form to add some information and a form to edit this information (then we can use on create and on update). For example: we have one User model and two different forms to add a user. During the registration a user can subscribe for a basic account or for an extended account. For the basic account is enough that the user will input just the username and password. For extended account the user is obligated to give also his personal data. To distinguish between these requests there is a checkbox (isextended) that the user can select if he wants to subscribe for extended account.

The problem appears while validating this form. How to indicate that the personal data is required in case the user is subscribing for extended account…? If we mark these fields as required in the model (var $validate) the validation rules will apply also if the user subscribe only for basic account. Consequently if the user subscribe for the basic account the form will not validate.

Well, the solution for the problem is very simply.

In the User model the var $validate table must have only rules for these fields that must validate always.

var $validate = array(
  'username' => array(
    'between' => array(
      'rule'      => array('between', 6, 20),
      'required'  => true,
     ),
  ),
  'password' => array(
    'empty' => array(
      'rule'      => 'notEmpty',
      'required'  => true,
    ),
  ),
);

Then we create another table with the same structure for example: $validate_extended with rules that must validate on some conditions – extended account.

var $validate_extended =array(
  'name' => array(
    'maxLength' => array(
      'rule'      => array('maxLength', 128),
      'required'=>true,
    ),
  ),
  'address' => array(
     'empty' => array(
      'rule'      => 'notEmpty',
      'required'  => true,
    ),
  ),
);

The validation is carried out just before save(). Therefore we can read from the $this->data[‘User’][‘isextended’] and if the request is for extended account we merge these two validation tables in one $validate.

class UsersController extends AppController {
(...)
function add() {
  if (!empty($this->data)) {

  if($this->data['User']['isextended']==1){
   $this->User->validate=array_merge($this->User->validate, $this->User->validate_extended);	
  }
	(...)		
  if ($this->User->save($this->data)) {...}
}
}
}

Enjoy.