The Definitive Guide to Validation in Craft, Part 4: Hidden Validator Settings
If you like the blog, you’ll love the book
The Definitive Guide to Craft Validation for Plugin Developers is practical guide to unlocking the hidden secrets of validation in Craft 2. It covers everything from the high-level concepts, right down to the nuts and bolts of implementation.
Buy it now, and download your copy immediately, in PDF, ePub, and Mobi formats.
Introduction
This is the fourth instalment in our series on validation in Craft. If you haven’t read parts one, two, and three, you should do so before continuing.
This instalment is all about “hidden” validator settings, which aren’t accessible via the usual Craft attribute rules.
What are “hidden” validator settings?
In this case, “hidden” is a bit of a misnomer. A more accurate description is that certain validator settings are not accessible via Craft attribute definitions.1
For example, the Yii CEmailValidator
class exposes a checkMX
setting. When this setting is true
, the validator will check the MX record for the given email address (it’s false
by default).
However, as you will recall from parts 2 and 3, Craft only lets us specify the minimum and maximum2 length of an email address.
This mismatch is down to the ModelHelper::getRules
method, which translates your attribute definitions into Yii-compatible validation rules. If the getRules
method doesn’t support a particular setting, it gets ignored.
How to specify a hidden setting
To use a hidden validator setting, you must directly modify the Yii-compatible validation rules generated by the ModelHelper::getRules
method. Gaining access to these rules is simple; just extend your model’s rules
method.
For example, let’s say we have the following Craft attribute definition, and wish to ensure that the CEmailValidator
checks the MX record for the given email address.
[
'username' => [
'type' => AttributeType::Email,
'required' => true,
]
],
Here’s how to do that:
public function rules()
{
// The rules generated by the ModelHelper::getRules method.
$rules = parent::rules();
// Our exciting rule manipulation code...
$rules[] = [ 'username', 'email', 'checkMX' => true ];
return $rules;
}
Overriding Craft-generated settings
Life gets a little more complicated if you need to override a hidden validator setting which is automatically generated by Craft. In that case, you must find the validator setting in the rules array, and delete it.
This functionality can be nicely encapsulated in a simple unsetRule
helper method, as follows.3
public function rules()
{
$rules = parent::rules();
$rules = $this->unsetRule($rules, 'username', 'integerOnly');
return $rules;
}
/**
* Removes the specified attribute setting from the rules array.
*
* @param array $rules
* @param string $attribute
* @param string $setting
*
* @return array
*/
protected function unsetRule(Array $rules, $attribute, $setting)
{
foreach ($rules as &$rule) {
if ($rule[0] == $attribute && array_key_exists($setting, $rule)) {
unset($rule[$setting]);
}
}
return $rules;
}
That’s the “how” taken care of, but what constitutes a Yii-compatible validation rule? And which “hidden” settings are available for each validator?
Read on for the answer to both of these questions.
A Yii validation rule primer
A Yii validation rule is an array with the following structure.4
[
'attributeName,otherAttributeName',
'validatorName',
'namedOption' => 'value',
]
Where:
- The first line is a comma-delimited string of attribute names;
- The second line is either the short name of a Yii validator, or the full classname (including namespace) of a custom validator;5
- Additional lines are name-value pairs, used to set validator properties.
The remainder of this section documents which Yii validation rules Craft generates for each of the available attribute rules. Feel free to skip it for now, and use it as a reference as and when you need it.
Each entry includes a quick one-line reminder of the purpose of the validation rule. If you want further details, check out the “attribute rules” instalment.
compare
The compare
validation rule compares two attribute values.
// Craft:
[
'password' => [
'type' => AttributeType::String,
],
'confirmPassword' => [
'type' => AttributeType::String,
'compare' => '==password',
],
]
// Yii:
[
[
'confirmPassword',
'compare',
'compareAttribute' => 'password',
'operator' => '==',
'allowEmpty' => 1
]
decimals
The decimals
validation rule specifies whether an attribute should accept non-integer values.
// Craft:
[
'integer' => [
'type' => AttributeType::Number,
],
'nonInteger' => [
'type' => AttributeType::Number,
'decimals' => 1,
],
]
// Yii
[
[
'integer',
'numerical',
'min' => -2147483648
'max' => 2147483647
'integerOnly' => 1
],
[
'nonInteger',
'numerical',
'min' => -2147483648
'max' => 2147483647
],
]
length
The length
validation rule specifies the required length of a string.
// Craft:
[
'sku' => [
'type' => AttributeType::String,
'length' => 10,
],
]
// Yii::
[ 'sku', 'length', 'is' => 10 ]
matchPattern
The matchPattern
validation rule specifies the regular expression used to validate the attribute value.
// Craft:
[
'usPhoneNumber' => [
'type' => AttributeType::String,
'matchPattern' => '/^\d{3}\-\d{3}\-\d{4}$/',
],
]
// Yii:
[
'usPhoneNumber',
'match',
'pattern' => '/^\d{3}\-\d{3}\-\d{4}$/'
]
max
The max
validation rule specifies the maximum value of a number.
// Craft:
[
'stanfordBinetScore' => [
'type' => AttributeType::Number,
'max' => 160,
],
]
// Yii:
[
'stanfordBinetScore',
'numerical',
'min' => -2147483648
'max' => 160
'integerOnly' => 1
]
maxLength
The maxLength
validation rule specifies the maximum length of a string.
// Craft:
[
'username' => [
'type' => AttributeType::String,
'maxLength' => 50,
],
]
// Yii:
[ 'username', 'length', 'max' => 50 ]
min
The min
validation rule specifies the minimum value of a number.
// Craft:
[
'age' => [
'type' => AttributeType::Number,
'min' => 0,
],
]
// Yii:
[
'age'
'numerical',
'min' => 0,
'max' => 2147483648,
'integerOnly' => 1
]
minLength
The minLength
validation rule specifies the minimum length of a string.
// Craft:
[
'password' => [
'type' => AttributeType::String,
'minLength' => 10,
],
]
// Yii:
[ 'password', 'length', 'min' => 10 ]
required
The required
validation rule is specifies whether an attribute value is required.
// Craft:
[
'username' => [
'type' => AttributeType::String,
'required' => true,
],
]
// Yii:
[ 'username', 'required' ]
reservedWords
The reservedWords
validation rule specifies a supplemental list of words reserved “handle” words.
// Craft:
[
'callSign' => [
'type' => AttributeType::Handle,
'reservedWords' => ['goose', 'iceman', 'jester', 'maverick'],
],
]
// Yii:
[
[
'callSign',
'Craft\HandleValidator',
'reservedWords' => ['goose', 'iceman', 'jester', 'maverick']
],
[
'callSign',
'length',
'max' => 255
]
]
unique
The unique
validation rule specifies whether the attribute value must be unique in the associated database column.
// Craft:
[
'superheroName' => [
'type' => AttributeType::String,
'unique' => true,
],
]
// Yii:
[ 'superheroName', 'unique' ]
values
The values
validation rule specifies a list of permissible attribute values.
// Craft:
[
'favoriteHipsterBand' => [
'type' => AttributeType::Enum,
'values' => [
'The Khan Incident',
'Thrift Store Boulevardiers',
'Neon Combover',
],
],
]
// Yii:
[
'favoriteHipsterBand',
'in',
'range' => [
'The Khan Incident',
'Thrift Store Boulevardiers',
'Neon Combover',
]
]
Which hidden settings are available?
Thankfully for all concerned, the Yii wiki includes an excellent validation rules reference, detailing the arguments supported by every Yii validator class.
This section documents the custom Craft validator classes.
Validator Class | Description |
---|---|
DateTimeValidator |
Does not expose any settings. |
HandleValidator |
Exposes a single setting, reservedWords . Use attribute rule of the same name to control this setting, as documented in the attribute rules instalment. |
LocaleValidator |
Does not expose any settings. |
UriValidator |
Exposes a single setting, pattern , which controls the regular expression pattern used to validate the URI. The default value is '/^[^\s]+$/' . |
UrlFormatValidator |
Exposes a single setting, requireSlug . The default value is true ; setting it to false disables the validator. |
UrlValidator |
A subclass of the CurlValidator class. Refer to the Yii documentation for details of the available validator settings. |
Conclusion
And so the penultimate part of this series draws to a close. You now know everything there is to know about Craft’s hidden attribute settings: what they are, what they do, and how to bend them to your will.
In the final instalment of the Definitive Guide to Validation in Craft we’ll cover writing your own custom validators, so don’t forget to check back at the same time next week (or just subscribe to our newsletter).
-
Unfortunately, that would have made for a somewhat cumbersome title. ↩︎
-
You may recall that the maximum length setting is hard-coded in the
CEmailValidator
class, rendering themaxLength
setting useless. ↩︎ -
If you’re feeling particularly fancy, you could easily move this to a base class or trait. ↩︎
-
Yii also includes support for “scenarios”, but it’s unlikely you’ll run into these within the context of a Craft application. The official Yii wiki contains a good explanation of scenarios. ↩︎
-
In the context of this definition, the term “custom validator” includes the built-in Craft validators. ↩︎