La API de configuración de WordPress, parte 7: Validación, desinfección y entrada
Spanish (Español) translation by Esther (you can also view the original English article)
Si acabas de unirte a nosotros, hemos cubierto muchos temas en esta serie, hemos intentado dar una visión completa de la API de configuración de WordPress, así como de sus funciones relacionadas. Hemos hablado de los ajustes, las opciones, la navegación y los menús. También hemos trabajado con ejemplos prácticos que emplean cada uno de los temas que hemos tratado.
Ya casi hemos terminado. En los dos últimos artículos de esta serie, vamos a echar un vistazo a la desinfección, la validación y los elementos de entrada básicos que podemos utilizar en nuestros plugins y temas de WordPress.
Antes de empezar: Este artículo asume que has seguido el resto de la serie, que tienes una copia de trabajo del código de muestra instalado y que estás relativamente familiarizado con la API de configuración y las opciones del tema. Si no estás seguro de nada de lo anterior, te recomiendo encarecidamente que leas el resto de los artículos antes de sumergirte en este post.
Comprender la validación y la desinfección
Antes de empezar a escribir cualquier código, tenemos que entender exactamente qué es lo que vamos a lograr, es decir, la validación y la desinfección. En pocas palabras, estos son los dos aspectos de la escritura y la lectura segura de datos de una página de opciones de WordPress y la base de datos subyacente.
Vamos a profundizar en esto cuando veamos cada uno de los tipos de entrada y trabajemos con los ejemplos, pero vamos a dar un poco de contexto a lo que realmente vamos a hacer:
- La validación es el proceso mediante el cual examinamos los datos que llegan desde la página de opciones o, mejor dicho, la entrada del usuario, y determinamos si es aceptable o no para guardar.
- La desinfección es el proceso mediante el cual nos aseguramos de que los datos que salen de la base de datos están limpios y con el formato adecuado para su representación en la página.
Quizás el resumen más conciso es que la validación debe hacerse antes de escribir los datos en la base de datos y la desinfección debe hacerse entre la lectura de los datos de la base de datos y su envío al navegador.
A menudo, la validación está relacionada con el almacenamiento de datos y la desinfección está relacionada con la recuperación de datos, pero también es posible desinfectar los datos después de que hayan pasado la validación para asegurarse de que solo se guardan datos limpios en la base de datos. Cuando trabajamos con nuestro propio código, es más fácil hacer esto; sin embargo, no siempre podemos depender de que otros desarrolladores hayan desinfectado sus datos, por lo que la responsabilidad de desinfectar todos los datos que salen de la base de datos recae en nosotros.
Actualizando nuestro proyecto
Para facilitar la comprensión de la validación y la desinfección, vamos a introducir una nueva pestaña en nuestra página de opciones. Si has introducido un nuevo menú de nivel superior, esto también va a requerir que añadamos un nuevo elemento de submenú, y que actualicemos la pestaña de visualización de opciones. Ocupémonos de eso ahora.
Primero, localiza la función sandbox_example_theme_menu y añade el siguiente elemento del submenú:
1 |
add_submenu_page( |
2 |
'sandbox_theme_menu', |
3 |
'Input Examples', |
4 |
'Input Examples', |
5 |
'administrator', |
6 |
'sandbox_theme_input_examples', |
7 |
create_function( null, 'sandbox_theme_display( "input_examples" );' ) |
8 |
);
|
A continuación, tenemos que seguir adelante y hacer una función que va a crear el grupo de opciones para nuestra nueva ficha de configuración. Suponiendo que hayas seguido la serie, esto debería ser fácil de seguir:
1 |
function sandbox_theme_initialize_input_examples() { |
2 |
|
3 |
if( false == get_option( 'sandbox_theme_input_examples' ) ) { |
4 |
add_option( 'sandbox_theme_input_examples' ); |
5 |
} // end if |
6 |
|
7 |
} // end sandbox_theme_initialize_input_examples |
8 |
add_action( 'admin_init', 'sandbox_theme_initialize_input_examples' ); |
Finalmente, necesitamos actualizar la función sandbox_theme_display para renderizar la pestaña y seleccionarla correctamente cuando se accede a ella a través de las pestañas o del elemento del submenú. En primer lugar, vamos a actualizar la condicional que examina la cadena de consulta y los argumentos de la función. En concreto, es necesario manejar el caso de los ejemplos de entrada. Actualiza el condicional para que se vea así:
1 |
if( isset( $_GET[ 'tab' ] ) ) { |
2 |
$active_tab = $_GET[ 'tab' ]; |
3 |
} else if( $active_tab == 'social_options' ) { |
4 |
$active_tab = 'social_options'; |
5 |
} else if( $active_tab == 'input_examples' ) { |
6 |
$active_tab = 'input_examples'; |
7 |
} else { |
8 |
$active_tab = 'display_options'; |
9 |
} // end if/else |
A continuación, tenemos que añadir una nueva pestaña a la navegación. Actualiza el contenedor nav-tab-wrapper para incluir esta nueva ancla:
1 |
<a href="?page=sandbox_theme_options&tab=input_examples" class="nav-tab <?php echo $active_tab == 'input_examples' ? 'nav-tab-active' : ''; ?>">Input Examples</a> |
Por último, tenemos que añadir una condicional más al elemento del formulario responsable de mostrar las opciones. Actualiza el condicional para que se vea así:
1 |
if( $active_tab == 'display_options' ) { |
2 |
|
3 |
settings_fields( 'sandbox_theme_display_options' ); |
4 |
do_settings_sections( 'sandbox_theme_display_options' ); |
5 |
|
6 |
} elseif( $active_tab == 'social_options' ) { |
7 |
|
8 |
settings_fields( 'sandbox_theme_social_options' ); |
9 |
do_settings_sections( 'sandbox_theme_social_options' ); |
10 |
|
11 |
} else { |
12 |
|
13 |
settings_fields( 'sandbox_theme_input_examples' ); |
14 |
do_settings_sections( 'sandbox_theme_input_examples' ); |
15 |
|
16 |
} // end if/else |
Asumiendo que has incluido todo el código correctamente, tu escritorio de administración debería tener este aspecto:


Ahora estamos listos para empezar a introducir nuevos elementos de opción y la funcionalidad de validación y desinfección. Si el código anterior te parece poco claro, asegúrate de revisar los artículos anteriores de la serie, ya que la configuración, las páginas de menú y las pestañas han sido cubiertas.
Los tipos de elementos
Hay cinco tipos de elementos básicos que podemos utilizar para la entrada en nuestras páginas de opciones de WordPress. Se trata de entradas, áreas de texto, casillas de verificación, botones de radio y cuadros de selección. En lo que queda de este artículo, vamos a echar un vistazo a los elementos de entrada y a las áreas de texto, y revisaremos los tres últimos en el último artículo de la serie.
Entrada
Los elementos de entrada son ideales para situaciones en las que necesitamos capturar una pequeña cantidad de texto de un usuario. Puede ser algo como su nombre o número de teléfono o algo un poco más complejo como una URL, su dirección de correo electrónico o una clave API. De hecho, ya estamos utilizando campos de entrada en la página "Opciones sociales" cuando pedimos las direcciones de los perfiles de las redes sociales del usuario.
La validación de la entrada de texto puede ser una operación compleja, especialmente si se quieren aplicar ciertas restricciones. Por ejemplo, los números de teléfono siguen un formato específico y si se pide a un usuario su número de teléfono, se puede configurar una función que determine si el número de teléfono se ajusta al formato estricto. Evidentemente, no podemos plasmar todos esos casos de uso en nuestros ejemplos, ya que es un campo demasiado amplio.
En cambio, lo que vamos a hacer es asegurarnos de que no se escriba ningún código malicioso en la base de datos. Esto significa que cuando un usuario introduzca texto en nuestro cuadro de texto, vamos a eliminar todas las etiquetas HTML y los caracteres potencialmente problemáticos. Pero antes de hacerlo, introduzcamos una nueva opción, entendamos el marcado y veamos qué ocurre si no aplicamos ningún tipo de validación.
Sigue adelante e introduce la nueva sección y el campo utilizando la función sandbox_theme_initialize_input_examples:
1 |
add_settings_section( |
2 |
'input_examples_section', |
3 |
'Input Examples', |
4 |
'sandbox_input_examples_callback', |
5 |
'sandbox_theme_input_examples'
|
6 |
);
|
7 |
|
8 |
add_settings_field( |
9 |
'Input Element', |
10 |
'Input Element', |
11 |
'sandbox_input_element_callback', |
12 |
'sandbox_theme_input_examples', |
13 |
'input_examples_section'
|
14 |
);
|
15 |
|
16 |
register_setting( |
17 |
'sandbox_theme_input_examples', |
18 |
'sandbox_theme_input_examples'
|
19 |
);
|
A continuación, define el llamada de retorno de la sección:
1 |
function sandbox_input_examples_callback() { |
2 |
echo '<p>Provides examples of the five basic element types.</p>'; |
3 |
}
|
Por último, introduce el elemento de entrada real que vamos a utilizar para capturar la entrada:
1 |
function sandbox_input_element_callback() { |
2 |
|
3 |
$options = get_option( 'sandbox_theme_input_examples' ); |
4 |
|
5 |
// Render the output
|
6 |
echo '<input type="text" id="input_example" name="sandbox_theme_input_examples[input_example]" value="' . $options[ 'input_example' ] . '" />'; |
7 |
|
8 |
}
|
Tu página de opciones debería tener ahora el aspecto de la siguiente imagen:


Comprensión del marcado
Hasta este punto, hemos estado creando nuestros elementos de opción y he mencionado que eventualmente discutiríamos cada uno de los atributos más adelante en la serie. Este es el artículo en el que empezamos a ver el significado de los atributos id y name.
Observa que al principio de la función, leemos las opciones de esta pestaña en particular usando la función get_option de WordPress. Esta función devolverá las opciones en un array. El atributo id del elemento de entrada identifica el valor de este elemento en el array. El atributo name es el nombre del array que tiene como clave el ID. ¿Tiene sentido?
Para estar completo, piénsalo de esta manera:
- WordPress creará un array basado en el nombre de la sección que hayas definido. En este caso, es
sandbox_theme_input_examples - Cada elemento será identificado por el atributo
id. En este ejemplo, es "input_example" - Puedes leer el valor de esta matriz utilizando
sandbox_theme_input_examples[input_example]
Así, el id del elemento representa la clave del valor en el array de opciones, el atributo name representa el nombre del array con la clave del valor en el array.
Añadir validación y desinfección
En este punto, es completamente posible comenzar a introducir valores en el elemento de entrada y guardar la opción. Inténtalo: establece un valor, haz clic en "Guardar cambios" y verás que el elemento de entrada muestra el valor que acabas de crear. Pero aquí está el problema: intenta pegar algo como esto en el campo de entrada:
1 |
<iframe src='http://wp.tutsplus.com' width='640' height='480'></iframe> |
A continuación, ve a index.php y añade el siguiente bloque de código:
1 |
<?php $input_examples = get_option('sandbox_theme_input_examples'); ?> |
2 |
<?php echo $input_examples['input_example']; ?> |
Actualiza la página de inicio y deberías notar que aparece un iframe en medio de la página de inicio de tu tema:


Parece una cuestión relativamente menor, pero es exactamente el tipo de cosas que tenemos que prevenir. No queremos que los usuarios tengan ese tipo de control sobre la base de datos, las páginas del sitio, etc. Por supuesto, guardar un simple iframe es un ejemplo menor, si los usuarios son capaces de insertar JavaScript, entonces pueden influir en ciertos aspectos de todo tu sitio. Más grave aún, si los usuarios son capaces de insertar SQL malicioso, tu base de datos podría verse comprometida.
Así que introduzcamos alguna validación. Como se mencionó anteriormente, queremos eliminar cualquier marca y caracteres problemáticos. Para ello, primero tenemos que definir una llamada de retorno de validación para nuestra sección de elementos de entrada. Para ello, revisemos la llamada register_setting y actualicémosla para que tenga el siguiente aspecto:
1 |
register_setting( |
2 |
'sandbox_theme_input_examples', |
3 |
'sandbox_theme_input_examples', |
4 |
'sandbox_theme_validate_input_examples'
|
5 |
);
|
A continuación, vamos a definir esa función:
1 |
function sandbox_theme_validate_input_examples( $input ) { |
2 |
} // end sandbox_theme_validate_input_examples |
Fíjate que esta función acepta un único parámetro que hemos llamado input. Este argumento representa el conjunto de opciones no validadas que WordPress está enviando a esta función desde la página de opciones que acabamos de guardar. Observa también que a medida que vayamos añadiendo elementos opcionales, iremos utilizando esta misma función.
La creación de una función de validación suele seguir tres pasos:
- Crear un array que se utilizará para almacenar las opciones validadas
- Validar (y limpiar, cuando sea necesario) todas las opciones entrantes
- Devuelve el array que hemos creado anteriormente
Hagamos eso ahora. Echa un vistazo a la siguiente aplicación prestando mucha atención a los comentarios:
1 |
function sandbox_theme_validate_input_examples( $input ) { |
2 |
|
3 |
// Create our array for storing the validated options
|
4 |
$output = array(); |
5 |
|
6 |
// Loop through each of the incoming options
|
7 |
foreach( $input as $key => $value ) { |
8 |
|
9 |
// Check to see if the current option has a value. If so, process it.
|
10 |
if( isset( $input[$key] ) ) { |
11 |
|
12 |
// Strip all HTML and PHP tags and properly handle quoted strings
|
13 |
$output[$key] = strip_tags( stripslashes( $input[ $key ] ) ); |
14 |
|
15 |
} // end if |
16 |
|
17 |
} // end foreach |
18 |
|
19 |
// Return the array processing any additional functions filtered by this action
|
20 |
return apply_filters( 'sandbox_theme_validate_input_examples', $output, $input ); |
21 |
|
22 |
}
|
La mayor parte del código debería ser relativamente sencillo, pero los dos aspectos más importantes vienen en la declaración dentro de la condicional y en la declaración de retorno.
- Estamos utilizando la función
strip_tags, que es nativa de PHP, para eliminar todas las etiquetas HTML y PHP - Estamos usando la función
stripslashes, que es otra función nativa de PHP, que manejará adecuadamente las comillas alrededor de una cadena.
Finalmente, podríamos haber devuelto simplemente el array $output al final de la función, pero devolver el resultado de la llamada a apply_filters es una buena práctica. Aunque excede el alcance de este artículo, vale la pena señalar que esta declaración básicamente llama a cualquier otra función que sea filtrada por esta función en particular antes de devolver el valor.
Ahora, intente dar algún ejemplo de entrada en el elemento de entrada. Intenta proporcionar una simple cadena, un número de teléfono, una dirección de correo electrónico, una URL, un bloque de HTML, una línea de JavaScript, etc. Genial, ¿eh?
Por último, volvamos a visitar index.php y hagamos un último cambio para demostrar cómo podemos realizar la desinfección de la salida. Recuerda que es una buena práctica desinfectar las opciones incluso si trabajas con valores que no provienen de tu propio trabajo.
Localiza la línea que dice:
1 |
<?php echo $input_examples[ 'input_example' ]; ?> |
Y actualízalo para que diga:
1 |
<?php echo sanitize_text_field( $input_examples[ 'input_example' ] ); ?> |
La función sanitize_text_field es otra función nativa de WordPress que está pensada específicamente para desinfectar la entrada del usuario desde los campos de texto o desde la base de datos.
Veremos más a lo largo de este artículo y el siguiente, pero hay una lista completa de estas funciones disponible en el Codex de WordPress.
Textarea
Al examinar los elementos de entrada, hemos cubierto mucho terreno. Por suerte, muchos de los mismos principios se aplican no solo a las áreas de texto, sino también al resto de los elementos. Por ello, no deberíamos dedicar tanto tiempo a cada elemento. Esto nos liberará para ver algunas de las idiosincrasias que vienen con cada uno de los tipos de elementos.
Por ahora, vamos a introducir un elemento textarea. En nuestro ejemplo, este elemento en particular permitirá a los usuarios introducir unas cuantas frases sobre sí mismos, piense en ello como una breve biografía. Primero, añade la siguiente llamada a la función sandbox_theme_initialize_input_examples:
1 |
|
2 |
add_settings_field( |
3 |
'Textarea Element', |
4 |
'Textarea Element', |
5 |
'sandbox_textarea_element_callback', |
6 |
'sandbox_theme_input_examples', |
7 |
'input_examples_section'
|
8 |
);
|
A continuación, vamos a definir la llamada de retorno necesaria para renderizar el textarea:
1 |
function sandbox_textarea_element_callback() { |
2 |
|
3 |
$options = get_option( 'sandbox_theme_input_examples' ); |
4 |
|
5 |
// Render the output
|
6 |
echo '<textarea id="textarea_example" name="sandbox_theme_input_examples[textarea_example]" rows="5" cols="50">' . $options[ 'textarea_example' ] . '</textarea>'; |
7 |
|
8 |
}
|
Observa que esta llamada se comporta de forma muy similar al elemento de entrada definido anteriormente. En concreto, hemos proporcionado un atributo id para dar a este valor una clave en el array de opciones y hemos especificado el nombre y la clave exactos en el atributo name del elemento. También hemos dado al textarea un tamaño determinado, aunque esto es puramente arbitrario.
Recordemos que como este elemento pertenece a la misma sección que el elemento de entrada, se procesa con la misma función de validación. Por lo tanto, obtenemos el mismo nivel de validación de forma gratuita. Pruébalo: intenta guardar marcas, scripts y otros tipos de código utilizando el área de texto.
Por último, actualicemos la página pública de nuestro tema para que recupere este valor y lo limpie adecuadamente para su visualización. En index.php, añade el siguiente bloque de código:
1 |
<?php if( $input_examples[ 'textarea_example' ] ) { ?> |
2 |
<?php echo sanitize_text_field( $input_examples[ 'textarea_example' ] ); ?> |
3 |
<?php } // end if ?> |
Aunque es prácticamente lo mismo que el campo de entrada, tenemos que asegurarnos de que somos completos en nuestra validación y desinfección.
Conclusión
Aunque solo hemos visto dos tipos de elementos, hemos cubierto mucho terreno. Además de actualizar nuestro tema, también hemos implementado la validación básica y hemos empezado a explorar las funciones de desinfección de WordPress.
En el último artículo, veremos los tres tipos de elementos restantes y cómo gestionarlos mediante la validación y la desinfección. Mientras tanto, experimenta con algo de lo que hemos tratado aquí y recuerda revisar los artículos de fuentes relacionadas enlazados al final del post.



