Registrar opciones
1. Visión general (flujo)
Cuando creas una página de ajustes en el Admin de WP normalmente sigues este flujo:
register_setting()— registras la opción (nombre enwp_options) y la función que la limpiará/validará.add_settings_section()— defines una sección —un bloque con título/descripcion— dentro de la página de ajustes.add_settings_field()— registras cada campo (input) que irá dentro de una sección. Le das un callback que pinta el HTML del campo.- En tu página de ajustes llamas a
settings_fields( $option_group ),do_settings_sections( $page )ysubmit_button()para que WP construya el formulario y gestione el guardado.
Resumen rápido:
register_setting()= guardar + sanitizar,add_settings_section()= organizar,add_settings_field()= dibujar inputs.
2. register_setting() — explicación detallada
Propósito: registrar una opción (o grupo de opciones) en WP, declarar su tipo por defecto y definir la función que la limpiará/validará antes de guardarla en la base de datos.
register_setting( string $option_group, string $option_name, array|string $args = array() );
- $option_group
- Nombre del grupo de ajustes. También es el valor que PASAS luego a
settings_fields(). - No confundir con la página; es el grupo al que pertenecen las opciones.
- Nombre del grupo de ajustes. También es el valor que PASAS luego a
- $option_name
- Nombre de la opción que se almacenará en
wp_options. Puede ser un string simple (opción individual) o el nombre de un array (p. ej.mi_plugin_options) que contendrá varias claves.
- Nombre de la opción que se almacenará en
- $args (array o string — preferir array) puede contener:
'type'—'string'|'integer'|'boolean'|'array'|'number'(ayuda a documentación/validación).'description'— texto descriptivo.'sanitize_callback'— función que recibe el valor enviado y debe devolver el valor limpio (oWP_Error/ usaradd_settings_error()para errores).'default'— valor por defecto si la opción no existe.'show_in_rest'— boolean o array para exponer la opción en la REST API.
Ejemplo mínimo (opción simple):
register_setting( 'mi_plugin_group', 'mi_plugin_items_per_page', array(
'type' => 'integer',
'sanitize_callback' => 'absint',
'default' => 5,
) );
Ejemplo (opción tipo array con función de sanitizado):
register_setting( 'mi_plugin_group', 'mi_plugin_options', array(
'type' => 'array',
'sanitize_callback' => 'mi_plugin_sanitize_options',
'default' => array( 'items_per_page' => 5, 'show_title' => 1 ),
) );
function mi_plugin_sanitize_options( $input ) {
$output = array();
// items_per_page => integer entre 1 y 50
$output['items_per_page'] = isset( $input['items_per_page'] ) ? absint( $input['items_per_page'] ) : 5;
if ( $output['items_per_page'] < 1 ) {
$output['items_per_page'] = 1;
add_settings_error( 'mi_plugin_options', 'items_per_page_error', 'El número mínimo es 1', 'error' );
}
if ( $output['items_per_page'] > 50 ) {
$output['items_per_page'] = 50;
add_settings_error( 'mi_plugin_options', 'items_per_page_max', 'El número máximo es 50', 'warning' );
}
// checkbox: puede venir vacío si está desmarcado
$output['show_title'] = ! empty( $input['show_title'] ) ? 1 : 0;
return $output;
}
Notas importantes:
- La sanitización siempre debe hacerse. Nunca confíes en los datos del usuario.
- La función puede usar
add_settings_error()para notificar errores y devolver un valor por defecto o corregido. - Si devuelves un
WP_Errorla opción no se actualizará (y el error se podrá mostrar). Es más común usaradd_settings_error()y devolver un valor seguro.
3. add_settings_section() — explicación detallada
Propósito: agrupar campos dentro de la página de ajustes, con un ID, título y (opcionalmente) una descripción o callback que muestre ayuda.
add_settings_section( string $id, string $title, callable $callback, string $page );
- $id — identificador único de la sección (ej.
'mi_section'). - $title — título visible de la sección.
- $callback — función que imprime texto/descripción para la sección (puede ser
__return_falsesi no quieres descripción). - $page — slug de la página de ajustes donde deberá imprimirse esta sección. (Este
$pagees el mismo valor que luego pasas ado_settings_sections( $page )cuando construyes la página).
Ejemplo:
add_settings_section(
'mi_section',
'Ajustes Generales',
function() { echo '<p>Configura las opciones principales del plugin.</p>'; },
'mi_plugin_page'
);
4. add_settings_field() — explicación detallada
Propósito: registrar un campo que aparecerá dentro de una sección específica. Le indicas un callback que dibuje el HTML del input.
add_settings_field( string $id, string $title, callable $callback, string $page, string $section = 'default', array $args = array() );
- $id — id único del campo (ej.
'items_per_page'). - $title — etiqueta visible para el campo.
- $callback — función que pinta el input. Recibe
$args(el último parámetro). - $page — debe coincidir con el
pageusado enadd_settings_section()y endo_settings_sections(). - $section — el id de la sección donde irá el campo.
- $args — array opcional con cualquier dato que quieras pasar al callback (por ejemplo
label_for,class,nombre_opcion, etc.).label_fores útil para vincular<label for="...">con eliddel input.
Ejemplo (uso de label_for):
add_settings_field(
'items_per_page',
'Items por página',
'mi_field_items_render',
'mi_plugin_page',
'mi_section',
array(
'label_for' => 'mi_items_per_page',
'class' => 'mi_row_class'
)
);
function mi_field_items_render( $args ) {
$options = get_option( 'mi_plugin_options', array() );
$value = isset($options['items_per_page']) ? $options['items_per_page'] : 5;
printf(
'<input id="%1$s" name="mi_plugin_options[items_per_page]" type="number" min="1" max="50" value="%2$s" />',
esc_attr( $args['label_for'] ),
esc_attr( $value )
);
}
Notas:
- Cuando el
option_namees un array (mi_plugin_options), en elnamedel input usasmi_plugin_options[campo]para que WP guarde todo como un array. - Si registraste la opción como opción individual (
mi_plugin_items_per_page), elnamedebe ser simplementemi_plugin_items_per_page.
5. Cómo construir la página de ajustes (markup habitual)
En el callback que pinta la página (p. ej. render_settings), normalmente incluyes:
function mi_plugin_render_page() {
if ( ! current_user_can( 'manage_options' ) ) return;
?>
<div class="wrap">
<h1>Mi Plugin — Ajustes</h1>
<?php
// Muestra errores/avisos registrados con add_settings_error()
settings_errors( 'mi_plugin_options' ); // opcional: filtrar por setting
?>
<form action="options.php" method="post">
<?php
// prints hidden fields (nonce, option_page, etc.) — el primer parámetro coincide con register_setting's option_group
settings_fields( 'mi_plugin_group' );
// imprime las secciones y campos registrados para la "page" (mi_plugin_page)
do_settings_sections( 'mi_plugin_page' );
// botón Guardar
submit_button();
?>
</form>
</div>
<?php
}
Puntos clave:
settings_fields( 'mi_plugin_group' )debe recibir exactamente el mismo option_group que usaste enregister_setting().do_settings_sections( 'mi_plugin_page' )mostrará todas las secciones y campos añadidos para esa página.submit_button()genera el botón y WP se encargará de procesar el guardado con las llamadas a la función de sanitización registrada.
6. Ejemplo completo y real (lista para copiar)
Plugin pequeño que registra un array de opciones, añade sección y dos campos:
<?php
/**
* Plugin Name: Ejemplo Settings API Completo
* Description: Ejemplo didáctico de register_setting, add_settings_section y add_settings_field.
* Version: 1.0
* Author: Tu Nombre
*/
if ( ! defined( 'ABSPATH' ) ) exit;
// Hook: registrar settings y campos
add_action( 'admin_init', 'ejemplo_settings_init' );
function ejemplo_settings_init() {
// 1) Registrar la opción (array)
register_setting( 'ejemplo_group', 'ejemplo_options', array(
'type' => 'array',
'sanitize_callback' => 'ejemplo_sanitize_options',
'default' => array(
'items_per_page' => 5,
'show_title' => 1
)
) );
// 2) Añadir sección
add_settings_section(
'ejemplo_section',
'Ajustes principales',
function() { echo '<p>Configura las opciones principales del plugin.</p>'; },
'ejemplo_page'
);
// 3) Añadir campo: items_per_page
add_settings_field(
'items_per_page',
'Items por página',
'ejemplo_field_items_render',
'ejemplo_page',
'ejemplo_section',
array(
'label_for' => 'ejemplo_items_per_page'
)
);
// 4) Añadir campo: show_title (checkbox)
add_settings_field(
'show_title',
'Mostrar título',
'ejemplo_field_showtitle_render',
'ejemplo_page',
'ejemplo_section',
array(
'label_for' => 'ejemplo_show_title'
)
);
}
// Render del campo items_per_page
function ejemplo_field_items_render( $args ) {
$options = get_option( 'ejemplo_options' );
$val = isset( $options['items_per_page'] ) ? $options['items_per_page'] : 5;
printf(
'<input id="%1$s" name="ejemplo_options[items_per_page]" type="number" min="1" max="50" value="%2$s" />',
esc_attr( $args['label_for'] ),
esc_attr( $val )
);
echo '<p class="description">Número de items a mostrar por página (1–50).</p>';
}
// Render del checkbox show_title
function ejemplo_field_showtitle_render( $args ) {
$options = get_option( 'ejemplo_options' );
$checked = ! empty( $options['show_title'] );
printf(
'<input id="%1$s" name="ejemplo_options[show_title]" type="checkbox" value="1" %2$s />',
esc_attr( $args['label_for'] ),
checked( 1, $checked, false )
);
echo '<label for="' . esc_attr( $args['label_for'] ) . '"> Mostrar el título en la lista</label>';
}
// Sanitización
function ejemplo_sanitize_options( $input ) {
$output = array();
$output['items_per_page'] = isset( $input['items_per_page'] ) ? absint( $input['items_per_page'] ) : 5;
if ( $output['items_per_page'] < 1 ) {
$output['items_per_page'] = 1;
add_settings_error( 'ejemplo_options', 'items_min', 'El valor mínimo es 1', 'error' );
}
if ( $output['items_per_page'] > 50 ) {
$output['items_per_page'] = 50;
add_settings_error( 'ejemplo_options', 'items_max', 'El valor máximo es 50', 'error' );
}
$output['show_title'] = ! empty( $input['show_title'] ) ? 1 : 0;
return $output;
}
// PÁGINA DE ADMIN (ej. desde add_menu_page llamas a esta función)
function ejemplo_render_page() {
if ( ! current_user_can( 'manage_options' ) ) return;
?>
<div class="wrap">
<h1>Ejemplo Settings API</h1>
<?php settings_errors( 'ejemplo_options' ); ?>
<form method="post" action="options.php">
<?php
settings_fields( 'ejemplo_group' ); // option_group de register_setting
do_settings_sections( 'ejemplo_page' ); // page usada en add_settings_section / add_settings_field
submit_button();
?>
</form>
</div>
<?php
}
(Para que la página sea accesible, añade un add_menu_page() que llame a ejemplo_render_page().)
7. Buenas prácticas y consejos útiles
- Sanitiza siempre (
sanitize_callback) y escapa al mostrar (esc_attr,esc_html…) — nunca confíes en el input del usuario. - Usa prefijos en nombres de opción para evitar colisiones (ej.
mi_plugin_). - Array vs opciones separadas:
- Guardar un array (
mi_plugin_options) es práctico (menos entradas enwp_options) y ordenado. - Guardar opciones separadas (
mi_plugin_items_per_page) puede ser más simple si son independientes.
- Guardar un array (
- Checkboxes: recuerda que si están desmarcadas no se envían; tu sanitizador debe poner
0ofalsesi la clave no existe. - Mostrar errores: usa
add_settings_error()dentro del sanitizador para notificar errores; en la página usasettings_errors()para mostrarlos. - Nonces & permisos:
settings_fields()genera el nonce para la opción; además, compruebacurrent_user_can()en tu callback de renderizado. - Cargar assets solo donde toca: usa
$hook_suffixdevuelto poradd_menu_page()para encolar scripts/estilos solo para tu página. - Depuración: si los campos no aparecen, revisa que los parámetros
pageyoption_groupcoincidan exactamente entreadd_settings_section(),add_settings_field(),register_setting()y tus llamadas ado_settings_sections()/settings_fields().
8. Errores comunes
- Usar nombres distintos para
option_groupenregister_setting()ysettings_fields()→ las opciones no se guardan correctamente. - Olvidar
name="mi_plugin_options[campo]"cuando registraste la opción como array → WP no guarda el subcampo. - No retornar el valor saneado en el
sanitize_callback→ la opción puede guardarse mal o no guardarse. - No llamar a
settings_errors()→ no verás los mensajes agregados conadd_settings_error().