Creating a custom validation rule

CakePHP provides a handful of validation rules out of the box, which together covers the need for most applications. The following table lists the built-in validation rules (found in CakePHP's Validation class.)

Rule

Purpose

_alphaNumeric

Checks that the value contains only integers or letters.

_between

Checks that the string length of the value is within the specified range.

_blank

Succeeds if the value is empty, or consists of only spaces (whitespaces, tabs, newlines, and so on).

_boolean

Checks if value can be interpreted as a Boolean.

_cc

Validates a credit card number.

_comparison

Compares the value to a given value, using the specified operator.

_custom

Validates the value using a custom regular expression.

_date

Validates the value as a date, using the given format or regular expression.

_decimal

Succeeds if value is a valid decimal number.

_email

Validates an e-mail address.

_equalTo

Succeeds if the value is equal to the given value.

_extension

Interprets the value as a file name and checks for the given extension.

_inList

Checks that the value is within a list of allowed values.

_ip

Validates an IP address.

_maxLength

Checks that the length of the string value does not exceed a certain number of characters.

_minLength

Similar to maxLength, but ensures that the string value has at least the given number of characters.

_money

Checks that the value is a valid monetary amount.

_multiple

Validates a multiple select against a set of options.

_numeric

Succeeds if the value is numeric.

_phone

Checks a phone number.

_postal

Validates a postal code.

_range

Succeeds if the value is within a numeric range.

_ssn

Checks a social security/national identity number.

_time

Validates the value as a time (24 hours format).

_uuid

Validates the value as a UUID.

_url

Succeeds if the value is a valid URL.

However, there are times where we require a custom validation, or where we need to change the way an existing validation works.

In this recipe, we will learn how to create our custom validation rule to check the validity of a given twitter user name.

Getting ready

We need some sample models to work with. Follow the Getting ready section of the recipe Adding multiple validation rules.

How to do it...

Edit the Profile model by opening your app/models/profile.php file and make the following changes:

class Profile extends AppModel {
public $validate = array(
'email' => array('rule' => 'notEmpty'),
'name' => array('rule' => 'notEmpty'),
'twitter' => array(
'rule' => 'validateTwitter',
'allowEmpty' => true,
'message' => 'This twitter account is not valid'
)
);
protected static $httpSocket;
protected function validateTwitter($data) {
if (!isset(self::$httpSocket)) {
App::import('Core', 'HttpSocket'),
self::$httpSocket = new HttpSocket();
}
$value = current($data);
self::$httpSocket->get('http://twitter.com/status/user_timeline/' . $value . '.json?count=1'),
return (self::$httpSocket->response['status']['code'] != 404);
}
}

If we now browse to http://localhost/profiles/add and click the Create button after entering a Nonexistent Twitter account, we should see the error message for the twitter field shown in the following screenshot:

How to do it...

If we instead specify a valid account, or leave it empty, there will be no error message displayed for the twitter field.

How it works...

When we set the rule validate option to the name of a method that is available in the model (validateTwitter() in our example), CakePHP calls that method when the field needs to be validated.

The method validateTwitter(), like any custom validation method, receives an array in its first argument. This array is indexed by the field name, and the value is set to the value entered by the user. In the example shown in the previous screenshot, the data argument comes in as:

array('twitter' => 'nonexistingtwitteraccount')

The validation method needs to return a Boolean value to indicate success: true if the validation succeeded, false if it failed. If we don't set the allowEmpty option to true, then the validation method will also be called when the field value is empty.

Note

If the custom validation method returns a string, the field is marked to have failed validation, and the returned string is used as the error message.

The method validateTwitter() first checks to see if an instance of the CakePHP HttpSocket class is already set. We use a static instance to make sure the class is initialized only once, thus avoiding unnecessary processing if the method is called several times for the same process.

Once we have the HttpSocket instance, we get the value to be validated (first value set in the array, as shown above), and we use it to fetch the contents of a twitter URL.

Note

We could have used an http://twitter.com/$account URL, which returns the HTML containing the user latest tweets. However we chose to use a JSON request, and limit the number of tweets to 1, to reduce bandwidth usage from our server

This publicly available Twitter URL is used to get the timeline for a Twitter account, which returns an HTTP status of 404 when the account is not registered with Twitter. If the status is indeed 404, we consider the Twitter account to be nonexistent, thus failing validation. Any other status code will result in a successful validation.

There's more...

Some custom validation methods need more than just the value to be validated to be able to tell if validation succeeded. Fortunately, CakePHP not only sends us an array of options utilized to perform the validation in the second argument, but also provides an easy way to add parameters to our validation methods. Using our example, we now want to be able to provide a different URL to use when checking the Twitter account.

To utilize the array of options, edit the Profile model by opening your app/models/profile.php file and make the following changes:

class Profile extends AppModel {
public $validate = array(
'email' => array('rule' => 'notEmpty'),
'name' => array('rule' => 'notEmpty'),
'twitter' => array(
'rule' => 'validateTwitter',
'allowEmpty' => true,
'url' => 'http://twitter.com/%TWITTER%'
)
);
protected function validateTwitter($data, $options) {
static $httpSocket;
if (!isset($httpSocket)) {
App::import('Core', 'HttpSocket'),
$httpSocket = new HttpSocket();
}
$options = array_merge(array(
'url' => 'http://twitter.com/status/user_timeline/%TWITTER%.json?count=1'
), $options);
$value = current($data);
$httpSocket->get(str_ireplace('%TWITTER%', $value, $options['url']));
return ($httpSocket->response['status']['code'] != 404);
}
}

If instead of utilizing the array of options, we want to utilize the ability to use extra parameters, we simply add arguments to our validation method, and pass those argument values as elements of the validate definition. To do so, edit the Profile model by opening your app/models/profile.php file and make the following changes:

class Profile extends AppModel {
public $validate = array(
'email' => array('rule' => 'notEmpty'),
'name' => array('rule' => 'notEmpty'),
'twitter' => array(
'rule' => array(
'validateTwitter',
'http://twitter.com/%TWITTER%'
),
'allowEmpty' => true
)
);
protected static $httpSocket;
protected function validateTwitter($data, $url = 'http://twitter.com/status/user_timeline/%TWITTER%.json?count=1') {
if (!isset(self::$httpSocket)) {
App::import('Core', 'HttpSocket'),
self::$httpSocket = new HttpSocket();
}
$value = current($data);
self::$httpSocket->get(str_ireplace('%TWITTER%', $value, $url));
return (self::$httpSocket->response['status']['code'] != 404);
}
}

See also

  • Adding multiple validation rules
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.222.155.187