How can I have a single sanitization callback for multiple fields and
then access the values of it ($input)?
For fields with the same validation logic, just set sanitize_callback
to the same callback, e.g. if field_1
and field_2
are single-line and text-only fields (i.e. no HTML allowed), you can use 'sanitize_callback' => 'sanitize_text_field'
for both fields. (see sanitize_text_field()
)
But for custom callbacks which need to access the option name (maybe because the callback is shared among different field types), then:
Option 1: Manually hook on sanitize_option_<option name>
register_setting()
uses the sanitize_option_<option name>
filter to register the sanitize callback, but the function calls add_filter()
with the fourth parameter set to the default (i.e. 1
) and thus, only one parameter that will be passed to the sanitize callback, so it won’t receive the option name (the $option
parameter in the example below).
Therefore if you want to receive the option name, then do not set the sanitize_callback
argument, and instead, manually hook on the above filter. E.g.
// Shared sanitize callback:
// Just a basic example of validating based on the option/input name.
function sanitize_any( $value, $option ) {
switch ( $option ) {
case 'field_1':
if ( empty( $value ) ) {
add_settings_error( 'my_plugin_messages', 'missing_field_1',
'Please enter a valid value into Field 1.' );
// Use the current database value. This will cancel saving the option.
$value = get_option( $option );
}
break;
// .. your code ...
}
return $value;
}
// Register the settings:
register_setting( 'option_group_1', 'field_1', array( 'default' => '' ) );
register_setting( 'option_group_2', 'field_2', array( 'default' => '' ) );
// Hook on sanitize_option_field_1 and sanitize_option_field_2:
add_filter( 'sanitize_option_field_1', 'sanitize_any', 10, 2 );
add_filter( 'sanitize_option_field_2', 'sanitize_any', 10, 2 );
/* Sample <input>:
<input name="field_1" value="<?php echo esc_attr( get_option( 'field_1' ) ); ?>">
*/
Option 2: Use an array
If the inputs belong in the same option group (i.e. same form), you can store them in an array which means field_1
and field_2
would be in a single database option, e.g. one named my_fields
. So for example:
// This function returns the default values for my_fields.
function my_fields_default_options() {
return array(
'field_1' => '',
'field_2' => '',
);
}
// The sanitize callback:
function sanitize_my_fields( $value ) {
$value = (array) $value;
if ( empty( $value['field_1'] ) ) {
add_settings_error( 'my_plugin_messages', 'missing_field_1',
'Please enter a valid value into Field 1.' );
// Use the current database value. This will cancel saving the option.
$value = get_option( 'my_fields' );
}
// .. your code ...
return $value;
}
// Register the setting:
register_setting( 'my_option_group', 'my_fields', array(
'sanitize_callback' => 'sanitize_my_fields',
'default' => my_fields_default_options(),
) );
/* And then in the <input> name, use the array format. E.g.
<input name="my_fields[field_1]" value="<?php echo esc_attr(
get_option( 'my_fields', my_fields_default_options() )['field_1']
); ?>">
*/