Skip to content

Custom validation ​

VX checks field values in two places:

  • In the editor, as people type. Each field carries a list of rules (maximum length, a pattern, a number range) that the editor evaluates live and shows as warnings.
  • On the server, when saving. Each field type cleans and checks its own value, for example trimming text, removing choices that don't exist, or rejecting a disallowed file. This is what Saving and validation describes.

You can add rules with the vxframework/fieldsets/validation_rules filter, and each rule you add is checked in both places. For example, to warn when a Book's sku doesn't start with PL-:

php
add_filter( 'vxframework/fieldsets/validation_rules', function ( array $rules, array $field ) {
    if ( ( $field['key'] ?? '' ) === 'sku' ) {
        $rules[] = [
            'type'    => 'pattern',
            'pattern' => '^PL-',
            'message' => 'SKUs start with PL-.',
        ];
    }
    return $rules;
}, 10, 2 );

The editor shows the message while the value doesn't match. Like VX's own rules, it's a warning: the value is still saved.

What a save does with your rules ​

Saves that go through VX check the rules you added: the classic post editor, the term and user screens, AI assistants, and your own code saving values through VX. A value that fails is saved anyway, and the failure is a warning. An AI assistant or your code gets the warning back in the result of the write, so it can tell the person or fix the value.

The block editor saves posts through WordPress rather than VX. Instead, it runs the same check live while you edit a post that has been saved at least once, and shows the warnings next to the fields.

A field hidden by conditional logic isn't checked, in the editor or on save.

Warning

Rules never stop a save. To refuse a value, check it in your own code, for example on WordPress's updated_post_meta action. Writes through the VX REST module can opt in to refusal: with vx_strict, any warning fails the write. See Writing values.

What the editor shows as people type ​

Every edit screen checks the built-in rule types on top-level fields as people type. Two kinds of rule are checked only on the server:

  • rules on fields inside a group or a repeater row
  • rule types of your own (below)

The block editor's live check shows these too. The other edit screens check them when you save, but don't show the warning.

Rule types of your own ​

When no built-in rule type fits, give the rule a type of your own and decide it in vxframework/fieldsets/validation_check. Return false when the value fails, and pass $valid through for rule types that aren't yours. This checks that an isbn field holds a valid ISBN-13:

php
add_filter( 'vxframework/fieldsets/validation_rules', function ( array $rules, array $field ) {
    if ( ( $field['key'] ?? '' ) === 'isbn' ) {
        $rules[] = [ 'type' => 'isbn13', 'message' => 'Enter a valid ISBN-13.' ];
    }
    return $rules;
}, 10, 2 );

add_filter( 'vxframework/fieldsets/validation_check', function ( $valid, array $rule, $value ) {
    if ( $rule['type'] !== 'isbn13' || $value === null || $value === '' ) {
        return $valid;
    }
    $digits = preg_replace( '/\D/', '', (string) $value );
    if ( strlen( $digits ) !== 13 ) {
        return false;
    }
    $sum = 0;
    foreach ( str_split( $digits ) as $i => $digit ) {
        $sum += (int) $digit * ( $i % 2 === 0 ? 1 : 3 );
    }
    return $sum % 10 === 0 ? $valid : false;
}, 10, 3 );

The callback is called for empty values too. Return $valid for them, as above, unless an empty value should fail.

Technical details for LLMs
  • Built-in rule types: required (disabled), minlength, maxlength, html_minlength, html_maxlength, min, max, min_items, max_items, min_files, max_files, min_count, max_count, item_minlength, item_maxlength, pattern (pattern, message), phone, date_range_order. Each rule: { type, …params, message, value_path? }. A rule with no message gets This value is not valid.
  • vxframework/fieldsets/validation_rules ( array $rules, array $field ) feeds the editor payload and the save check. Message templates: vxframework/fieldsets/validation_messages.
  • Save check: only rules the filter added. The field type's own rules (from its settings, e.g. maxlength) are checked by its normalization instead; a callback that only changes their message adds nothing. A required rule is skipped. Rules run against the normalized value; warning paths look like sku, box.inner, lines.0.line.
  • vxframework/fieldsets/validation_check ( ?bool $valid, array $rule, $value ): false adds the rule's message as a warning at the field's path; null or true passes.
  • Block editor live check: the fieldset values validate endpoint, run for saved posts; it lists warnings in errors. The editor shows a message once when its own check reports the same path and text.

Documentation for the VX Framework.