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).


  1. Unfortunately, that would have made for a somewhat cumbersome title. ↩︎

  2. You may recall that the maximum length setting is hard-coded in the CEmailValidator class, rendering the maxLength setting useless. ↩︎

  3. If you’re feeling particularly fancy, you could easily move this to a base class or trait. ↩︎

  4. 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↩︎

  5. In the context of this definition, the term “custom validator” includes the built-in Craft validators. ↩︎

Bend Craft to Your Will

Our newsletter helps you make the most of Craft. Join for free, leave any time.