Validar un array de opciones
Utilizamos la función predeterminada de WordPress register_setting()
para validar opciones del tema. Esta llamada, por ejemplo:
register_setting( 'options-group', 'option1', 'intval' );
Validará si $option1
es un entero o no.
¿Qué puedo usar para pasar un array de opciones y validar cada miembro del array?
Por ejemplo:
$options = array(
'options1' => 4, // intval
'options2' => '127.0.0.1', // dirección IP
'options3' => 'test@test.com' // dirección de correo
);

Lo que necesitas hacer es construir tu propia función de validación de datos. Ozh escribió un gran tutorial sobre esto anteriormente, pero aquí está la esencia de ello...
Supongamos que tu array de opciones se llama $my_options
y contiene tres campos, 'text'
, 'age'
, y 'isauthorized'
.
Lo registrarías de la misma manera:
register_setting( 'my_setting', 'my_options', 'my_validation_function' );
¿Pero ves cómo usamos un callback personalizado para el tercer parámetro? Ahora solo necesitamos definir esa función personalizada:
function my_validation_function( $input ) {
// Validar age como un entero
$input['age'] = intval( $input['age'] );
// Eliminar etiquetas HTML del texto para hacerlo seguro
$input['text'] = wp_filter_nohtml_kses( $input['text'] );
// Asegurar que isauthorized solo sea verdadero o falso (0 o 1)
$input['isauthorized'] = ( $input['isauthorized'] == 1 ? 1 : 0 );
return $input;
}
Alternativamente
Si deseas hacer tus funciones de validación un poco más flexibles, puedes usar los filtros incorporados de WordPress para evitar repetir tu código. Todavía registras tu validación de la misma manera:
register_setting( 'my_setting', 'my_options', 'my_validation_function' );
Pero en lugar de verificar cada elemento de tu array dentro de la función de validación, iteras a través del array y delegas a los filtros:
function my_validation_function( $input ) {
foreach( $input as $key => $value ) {
$input[$key] = apply_filters( 'my_validation_' . $key, $value );
}
return $input;
}
Ahora puedes enganchar cualquier lógica de validación que necesites:
add_filter( 'my_validation_age', 'validate_numeric' );
function validate_numeric( $numeric ) {
return intval( $numeric );
}
add_filter( 'my_validation_text', 'validate_text' );
function validate_text( $text ) {
return wp_filter_nohtml_kses( $text );
}
add_filter( 'my_validation_isauthorized', 'validate_bool' );
function validate_bool( $bool ) {
return $bool == 1 ? 1 : 0;
}
Si no agregas un filtro para una de tus opciones, entonces el valor de la opción permanecerá sin cambios. Los filtros también son la forma en que deseas proceder con funciones que devuelven contenido, y puedes agregar tantos como quieras... o adjuntar tus filtros a cualquier campo.
Digamos que tenías dos campos numéricos en tu array - age
y numberChildren
. En lugar de crear una función de validación adicional que pueda manejar el campo numberChildren
, simplemente lo agregas al filtro:
add_filter( 'my_validation_numberChildren', 'validate_numeric' );

Me gusta este enfoque alternativo, pero ¿cómo manejarías el guardado de las casillas de verificación? Solo se envían por POST si están marcadas, por lo que el bucle foreach
que recorre cada resultado no guardará una casilla desmarcada.

Chicos, ¿cómo es esta validación? Si una entrada es incorrecta, nada debería guardarse, el usuario debería ver la entrada incorrecta y un mensaje de validación útil. add_settings_error()
es la solución.

Esto no es validación sino saneamiento. Sin embargo, WordPress tiene una gran cantidad de funciones mal diseñadas o mal nombradas. Esta en particular está sobrecargada tanto con saneamiento como validación. Para no actualizar la opción debido a valores inválidos, simplemente devuelve el valor anterior. También es recomendable agregar un error útil usando add_settings_error().

Parece que la solución de "uso de funciones diferentes para cada opción en el array" no es como en mis sueños, pero creo que esto debería funcionar:
register_setting( 'my_setting', 'my_options', 'my_validation_function' );
function my_validation_function( $input ) {
foreach ($input as $option=>$value){
do_action('my_validation_'.$option, $option, $value);
}
return $input;
}
Y luego puedo usar funciones personalizadas para la validación de cada opción así:
add_action('my_validation_age', 'my_validation_function_for_age', 10, 2);
function my_validation_function_for_age($option, $value) {
$input[$option] = intval( $value );
}
add_action('my_validation_text', 'my_validation_function_for_text', 10, 2);
function my_validation_function_for_text($option, $value) {
$input[$option] = wp_filter_nohtml_kses( $value );
}
add_action('my_validation_isauthorized', 'my_validation_function_for_isauthorized', 10, 2);
function my_validation_function_for_isauthorized($option, $value) {
$input[$option] = ( $value == 1 ? 1 : 0 );
}
Escribo aquí para futuros visitantes. Aceptando la solución de EAMann.
