Creating a custom validation method

CakePHP offers a lot of handy built-in validation methods for common field types, such as email addresses, dates, even credit card numbers.

If you can’t find what you need among these methods and your needs are pretty straightforward, you can write a custom regular expression.

If your needs are a little more complicated, you can also write a custom validation method. This involves writing a function to perform the validation, then adding that function name as a rule to all fields you want thusly validated.

Let’s say we have a form to collect address data. We have the the usual set of fields: street address, city, state, zip. But, because we’re cosmopolitan citizens of the world, we also have a “country” field in case, you know, France.

As only US addresses need a state, we add the option “outside US”, with a value of “none”, to our state dropdown but this is not enough. We need custom validation.

We start with the validation function. Here’s what we want, in pseudo-code:

if (country IS "United States" && state ISN'T "outside US") {
   // valid US address
} else if (country ISN'T "United States" && state IS "outside US") {
   // valid non-US address
} else {
   // something's wonky so throw an error
}

Here’s the actual function, added to our “Address” model:

public function checkStateCountry($check) {
   $state = $this->data['Address']['state'];
   $country = $this->data['Address']['country'];
   if (($country == 'United States' && $state != 'none') ||
      ($country != 'United States' && $state == 'none')) {
      return true;
   }
   return false;
}

The two valid configurations have been collapsed into a single conditional statement that returns true. If neither of these conditions are met the function returns false by default, prompting CakePHP to puke out an error.

Now we need to add this function as a rule to the appropriate field, as well as include the message we want users to see:

$validate = array(
   'state' => array(
      'rule' => 'checkStateCountry',
      'message' => 'If the event is in the US, select a state from this dropdown and enter "United States" as the country below. If the event is outside the US, select "outside US" from this dropdown and enter the country below.'
   )
);

If our intrepid user misconfigures the state and country fields, they’ll see our verbose but hopefully useful error message.