Jonathon Snook wrote about multiple validation sets in CakePHP and it reminded me how often we require rather different sets of validation rules for a single model. I have always enjoyed learning how others approached similar problems so I think I shall share mine too.
A very relevant example is the User model where we usually have multiple forms associated. E.g. sign up, profile updates, password reset, etc. Each form have a different set of fields while some share the same fields. My approach is to select a different set of fields for each “action” and modify the rules if required. This means I’ll keep a master set of rules for all the User model fields and call setValidate()
for each “action”.
/** * Set the default validation rules here. * * @var array */ protected $_validate = array( 'username' => array( 'empty' => array( 'required' => true, 'rule' => VALID_NOT_EMPTY, 'last' => true ), 'invalid' => array( 'rule' => '/^[\w]{3,30}$/', 'last' => true, 'on' => 'create' ), 'exists' => array( 'rule' => 'validateUniqueUsername', 'last' => true, 'on' => 'create' ) ), 'password' => array( 'empty' => array( 'required' => true, 'rule' => VALID_NOT_EMPTY, 'last' => true ), 'invalid' => array( 'required' => true, 'rule' => '/^.{6,30}$/', 'last' => true ) ), ... ); /** * Sets just enough fields for validation. * * @param array $fields List of field names to validate against. If no param * passed, all fields will be included. * @author Derick */ function setValidate($fields = null) { if ($fields === null) { $this->validate = $this->_validate; } else { $this->validate = array(); foreach ($fields as $f) { if (isset($this->_validate[$f])) { $this->validate[$f] = $this->_validate[$f]; } } } }
This is a simplified example in my User model where I have the register()
function to validate only the fields required for sign up and the updateProfile()
function which uses another set of fields with slight different requirement.
function register($data) { $fields = array('username', 'password', ...); $this->setValidate($fields); $this->save($data, true, $fields); } function updateProfile($data) { $fields = array('password', ...); $this->setValidate($fields); // derick: allow user to left password field empty unset($this->validate['password']['empty']); $this->validate['password']['invalid']['allowEmpty'] = true; $this->save($data, true, $fields); // derick: you can also call this again to "reset" to the default set of // rules but usually we don't need this $this->setValidate(); }
In other words, I only update the $validate
array in the model when required. Some might think it is dangerous since there is a chance of saving data without validation but this works for me. What do the rest of you do?