Skip to main content

Validation Hooks Reference (PHP)

Form Plant's server-side validation can be customized freely through WordPress filter hooks. From replacing error messages to per-field custom checks and external API integration, everything can be implemented simply by adding a PHP filter.

Choosing between client-side and server-side customization

Use JavaScript customization for instant in-browser feedback ( better UX ), and the PHP hooks on this page for reliable validation ( security ). Client-side checks can easily be bypassed with tools such as DevTools, so input validation must always be performed on the server side as well.

Hooks other than validation

This page covers validation-specific hooks only. For hooks related to email delivery, post-submission actions, redirects, file uploads, dynamic choice generation, form settings, and so on, see the PHP Hook Reference.

Hook List

fplant_before_validation

Processes data before validation begins. Useful for normalizing phone numbers, converting full-width to half-width characters, and similar tasks.

ParameterTypeDescription
$dataarraySubmitted data
$fieldsarrayField settings
$form_idintForm ID

Return value: array — the processed submitted data


fplant_validation_required_message

Customizes the error message for required fields.

ParameterTypeDescription
$messagestringDefault error message
$fieldarrayField settings
$valuemixedInput value
$dataarrayThe entire submitted data

Return value: string — the customized error message


fplant_validate_field_{$field_name}

Completely overrides validation for a specific field. The field name ( e.g. email ) is embedded in the hook name.

ParameterTypeDescription
$errornullInitial value
$fieldarrayField settings
$valuemixedInput value
$dataarrayThe entire submitted data
$form_idintForm ID

Return value:

  • null — run the standard validation
  • false — no error ( skip the standard validation )
  • string — error message ( skip the standard validation )
warning

Returning anything other than null skips the standard validation. If you also want the standard checks to run, return null.

note

This hook only fires for fields that have a value ( file fields excepted ) . Fields with an empty value ( more precisely, any empty value other than '0' ) are skipped before this hook, so fplant_validate_field_{name} is not called ( empty fields are left to the standard required check by design ) . It therefore cannot be used for validation conditioned on emptiness ( e.g. making a field required based on another field's value ) . For that, use fplant_validation_errors, which fires for the whole form.


fplant_validation_message_email

Customizes the error message for email address fields.

ParameterTypeDescription
$messagestringDefault error message
$fieldarrayField settings
$valuestringInput value
$contextarrayContext information ( type: 'format' )

Return value: string


fplant_validation_message_url

Customizes the error message for URL fields. The parameters are the same as fplant_validation_message_email.


fplant_validation_message_tel

Customizes the error message for phone number fields. The parameters are the same as fplant_validation_message_email.


fplant_validation_message_number

Customizes the error message for number fields.

ParameterTypeDescription
$messagestringDefault error message
$fieldarrayField settings
$valuestringInput value
$contextarraytype: 'format' / 'min' / 'max', min, max

Return value: string


fplant_validation_message_password

Customizes the error message for password fields.

ParameterTypeDescription
$messagestringDefault error message
$fieldarrayField settings
$valuestringInput value
$contextarraytype: 'min_length' / 'strength'

Return value: string


fplant_validation_message_postal_code

Customizes the error message for postal code fields. It also fires for the postal code subfield inside an address ( address ) field.

ParameterTypeDescription
$messagestringDefault error message
$fieldarrayField settings
$valuestringInput value
$contextarrayContext information ( type: 'format' )

Return value: string


fplant_validation_message_name_kana

Customizes the kana-validation error message for the name ( furigana ) field. This is the only hook that does not have a fourth argument ( $context ).

ParameterTypeDescription
$messagestringDefault error message
$fieldarrayField settings
$valuestringInput value

Return value: string


fplant_validate_field_type_{$field_type}

Additional validation per field type ( email, tel, number, etc. ). It runs after the standard validation.

ParameterTypeDescription
$errorfalse / stringResult of the standard validation
$fieldarrayField settings
$valuemixedInput value

Return value: false ( no error ) or string ( error message )


fplant_validation_message_min_length

Customizes the minimum character count error message.

ParameterTypeDescription
$messagestringDefault error message
$fieldarrayField settings
$valuestringInput value
$validationarrayValidation settings

Return value: string


fplant_validation_message_max_length

Customizes the maximum character count error message. The parameters are the same as fplant_validation_message_min_length.


fplant_validation_message_pattern

Customizes the regular expression pattern error message. The parameters are the same as fplant_validation_message_min_length.


fplant_validate_custom_rules

Adds custom validation rules. By defining your own key in the field's validation array and writing the check logic in this hook, you can implement new rules.

ParameterTypeDescription
$errorfalse / stringResult of the existing error checks
$fieldarrayField settings
$valuestringInput value
$validationarrayValidation settings

Return value: false ( no error ) or string ( error message )


fplant_validation_message_file

Customizes the file upload error message.

ParameterTypeDescription
$messagestringDefault error message
$fieldarrayField settings
$filearrayThe $_FILES array
$contextarraytype: 'upload_error' / 'size' / 'extension', max_size, allowed_types

Return value: string


fplant_validation_errors

A hook for making a final adjustment to the entire error array after every field has been validated.

ParameterTypeDescription
$errorsarrayError array
$fieldsarrayField settings
$dataarraySubmitted data

Return value: array


Hook Execution Order

When fplant_validate_field_{name} returns anything other than null, the standard validation ( everything below "Standard validation" in the diagram above ) is skipped.


Examples

Example 1: Localizing the Required Error Message

add_filter( 'fplant_validation_required_message', function( $message, $field ) {
if ( get_locale() === 'en_US' ) {
return sprintf( '%s is required', $field['label'] );
}
return $message;
}, 10, 2 );

Example 2: Restricting Validation to Company Email Domains

add_filter( 'fplant_validate_field_company_email', function( $error, $field, $value, $data, $form_id ) {
$allowed_domains = array( 'example.com', 'company.co.jp' );

if ( ! empty( $value ) && is_email( $value ) ) {
$domain = substr( strrchr( $value, '@' ), 1 );

if ( ! in_array( $domain, $allowed_domains, true ) ) {
return 'Please enter a company email address (@example.com or @company.co.jp).';
}
}

// Returning null also runs the standard validation.
return $error;
}, 10, 5 );

Example 3: Adding a Rule That Forbids Toll-Free Numbers for the Tel Type

add_filter( 'fplant_validate_field_type_tel', function( $error, $field, $value ) {
// If there is already an error, return it.
if ( $error !== false ) {
return $error;
}

$cleaned_tel = preg_replace( '/[^0-9]/', '', $value );
if ( strpos( $cleaned_tel, '0120' ) === 0 || strpos( $cleaned_tel, '0800' ) === 0 ) {
return sprintf( 'Toll-free numbers cannot be used for %s.', $field['label'] );
}

return false;
}, 10, 3 );

Example 4: Adding a Custom "Age Restriction" Rule

add_filter( 'fplant_validate_custom_rules', function( $error, $field, $value, $validation ) {
if ( isset( $validation['age_restriction'] ) && ! empty( $value ) ) {
$min_age = intval( $validation['age_restriction'] );
$input_age = intval( $value );

if ( $input_age < $min_age ) {
return isset( $validation['age_restriction_message'] )
? $validation['age_restriction_message']
: sprintf( 'Only people aged %s or older may apply.', $min_age );
}
}

return $error;
}, 10, 4 );

Example 5: Verifying a Postal Code Against an External API ( cached with Transients )

add_filter( 'fplant_validate_field_postal_code', function( $error, $field, $value, $data, $form_id ) {
// This hook does not fire for empty values, so this guard is effectively unreachable ( defensive )
if ( empty( $value ) ) {
return $error;
}

$cache_key = 'postal_code_' . md5( $value );
$cached = get_transient( $cache_key );

if ( false !== $cached ) {
return $cached === 'valid' ? false : $cached;
}

$response = wp_remote_get(
'https://api.zipaddress.net/?zipcode=' . urlencode( $value ),
array( 'timeout' => 5 )
);

if ( is_wp_error( $response ) ) {
return 'Failed to verify the postal code. Please try again later.';
}

$body = wp_remote_retrieve_body( $response );
$result = json_decode( $body, true );

if ( empty( $result['data'] ) ) {
$message = 'Please enter a valid postal code.';
set_transient( $cache_key, $message, HOUR_IN_SECONDS );
return $message;
}

set_transient( $cache_key, 'valid', HOUR_IN_SECONDS );
return false;
}, 10, 5 );

Example 6: Normalizing Submitted Data ( removing hyphens, full-width to half-width )

add_filter( 'fplant_before_validation', function( $data, $fields, $form_id ) {
foreach ( $fields as $field ) {
if ( ! isset( $data[ $field['name'] ] ) ) {
continue;
}

// Remove hyphens and similar characters from phone numbers.
if ( $field['type'] === 'tel' ) {
$data[ $field['name'] ] = preg_replace( '/[^0-9]/', '', $data[ $field['name'] ] );
}

// Convert full-width to half-width for number fields.
if ( $field['type'] === 'number' ) {
$data[ $field['name'] ] = mb_convert_kana( $data[ $field['name'] ], 'n' );
}
}

return $data;
}, 10, 3 );

Example 7: Customizing the File Size Error Message

add_filter( 'fplant_validation_message_file', function( $message, $field, $file, $context ) {
if ( $context['type'] === 'size' ) {
return sprintf(
'The file for %s is too large. Please choose a file of %sMB or less (current: %sMB).',
$field['label'],
$context['max_size'],
round( $file['size'] / 1024 / 1024, 2 )
);
}

return $message;
}, 10, 4 );

Best Practices

How to Return Errors

// ✅ Return a string when there is an error.
return 'Error message';

// ✅ Return false when there is no error.
return false;

// ❌ Do not return null or true (except for fplant_validate_field_{$field_name}).

Performance Considerations

Validators that call external APIs should always cache results with the Transient API or similar. Hitting the API on every form submission can cause display delays and trigger API rate limits.

Security Considerations

  • Always sanitize input values with sanitize_text_field() or similar.
  • Set a timeout on external API requests.
  • When including input values in error messages, escape them with esc_html().

Summary

By using PHP filter hooks, all of the following customizations are handled entirely on the server side.

  • Localizing and rewording error messages
  • Extending validation per field type
  • Adding custom validation to specific fields
  • External API integration validation
  • Adding custom validation rules
  • Normalizing data before validation