Custom validation rules
The built-in rules cover most needs (see Validation rules), but you can add your own with the octa_forms_validation_rules filter. Once registered, a rule is used by its name in any form’s config, exactly like a built-in one.
Registering a rule
Section titled “Registering a rule”The filter receives a map of rule name to a callable. Add your entry and return the map:
add_filter( 'octa_forms_validation_rules', function ( array $rules ) { $rules['even'] = function ( $value, array $params ): bool { return is_numeric( $value ) && (int) $value % 2 === 0; }; return $rules;} );Now any field can use it:
{ "name": "seats", "type": "text", "label": "Seats", "rules": [{ "r": "even" }] }The callable contract
Section titled “The callable contract”Your callable receives:
$value— the field’s submitted value. Usually a string. For checkboxes it is a boolean, and for file fields it is the list of uploads.$params— an array of parameters parsed from the rule string. For{ "r": "between:1,10" }your callable receives['1', '10'].
It must return true when the value passes and false when it does not. Return false on unexpected input rather than throwing, so a malformed value fails closed.
Parameters
Section titled “Parameters”Parameters come after a colon in the rule string, split on commas:
{ "r": "between:1,10" }$rules['between'] = function ( $value, array $params ): bool { [ $lo, $hi ] = array_map( 'intval', $params + [ 0, 0 ] ); return is_numeric( $value ) && (int) $value >= $lo && (int) $value <= $hi;};The regex rule is the exception: its pattern is taken literally and never split, so a comma inside your pattern is safe.
Error messages
Section titled “Error messages”A custom rule uses the message you put in the field’s rule with the m key. If you leave m out, provide a sensible message there, because there is no built-in default text for a rule OctaForms does not ship:
{ "r": "between:1,10", "m": "Please pick a number from 1 to 10." }A note on trust
Section titled “A note on trust”A value that passes your rule is still untrusted input. Escape it on output like any other user data. Rules decide acceptance; they do not sanitize.