Como desarrollar y alimentar una página de opciones en WordPress

En este artículo, voy a detallar cómo crear páginas de opciones en WordPress con subpáginas, añadir campos personalizados, implementar un repeater de forma nativa y cómo guardar y recuperar esos datos desde la base de datos. Este proceso lo voy a realizar exclusivamente con funciones nativas de WordPress. (Para cuando queremos evitar plugins como Advanced Custom Field PRO o similares).

Crear una página de opciones en WordPress puede ser útil en una amplia variedad de proyectos, especialmente cuando se necesita centralizar configuraciones que afectan a varias partes del sitio. Aquí te dejo una lista de los tipos de proyectos donde tener una página de opciones puede ser una excelente idea. Además te indico algunas configuraciones que podrían encajar en cada proyecto.

¿Donde integrar una página de opciones?

  • Desarrollo de Temas personalizados, para personalizar aspectos del tema sin necesidad de editar código como colores, tipografías predeterminadas, logo, favicon, configuraciones del Header y Footer, activar o desactivar elementos o secciones, datos de contacto para mostrar en varias partes del sitio…
  • Configuración general de plugins. Cuando desarrollas un plugin personalizado puedes proporcionar una interfaz para configurar su funcionalidad. Como: configurar claves API y endpoints para servicios externos, activar o desactivar funciones…
  • Webs de empresa para centralizar configuraciones y ofrecer al cliente una interfaz fácil que el mismo pueda manipular. Por ejemplo: nombre de la empresa, dirección, horarios, teléfonos, emails, redes sociales, temas legales…
  • Tiendas Online, agregando configuraciones personalizadas en casos específicos como métodos de envío, pasarelas de pago, reglas de descuento o promociones, configurar productos destacados, banners promocionales…
  • Blogs o sitios de contenido, para controlar aspectos globales como: configuración de formato de fecha/hora, estilo visual de las entradas (Rejilla, lista…), anuncios, banners publicitarios, personalización de categorías y etiquetas…
  • Multisitios, crea paginas de opciones para cada sitio de un multisitio donde puedan controlar aspectos globales por ejemplo: controlar el branding, colores, logotipo, política de privacidad, política de cookies, aviso legal, restricciones por rol de usuario, configuración del dominio…
  • Sitios Multilingües, para centralizar configuraciones de idiomas como: idiomas disponibles, traducción de cadenas de texto, configuración del selector de idiomas (diseño, posicionamiento…).
  • Proyectos con integraciones complejas como CRMs, ERPs, APIs o plataformas de tercero. Ofreciendo una pagina para poder añadir cosas como Claves API, opciones de autenticación OAuth…
  • Sitios web dinámicos (Periódico, revista online…), teniendo una página de opciones para definir todas esas reglas globales que hacen que el sitio se actualice automáticamente con nuevos contenidos. Control total de filtros (creados con WP_Query por ejemplo), configurar notificaciones…

¿Qué se puede incluir en una página de opciones?

Una página de opciones puede contener:

  • Campos de texto.
  • Áreas de texto.
  • Campos de URL
  • Checkbox y radio buttons. (Checkboxes con o sin multiselector)
  • Selectores desplegables. (Con o sin multiselector)
  • Switch / toggle: Un interruptor gráfico para activar / desactivar una opción.
  • Repetidores.
  • Carga de imágenes, videos o archivos.
  • Configuraciones condicionales. Aparecen o cambian su estado en función de la selección en otros campos.
  • Sliders numéricos o de rango.
  • Color pickers (selectores de color).
  • Data pickers (selectores de fecha).
  • Date-time pickers: Selección de fechas y horas juntas.
  • Time pickers: Selección específica de horas.
  • Tabla editable con filas y columnas definidas. Útil para datos tabulares.
  • Galerías: Selección de múltiples imágenes o videos.
  • Editor WYSIWYG.
  • Campos dinámicos (listado de roles, categorías, usuarios…)
  • Shortcodes dinámicos.
  • Datos para integraciones API.
  • y muchos más…

¿Necesitas un desarrollo web a medida?

Me especializo en desarrollar sitios webs avanzados, programando soluciones personalizadas para proyectos web.

Comenzamos…

Ahora que tenemos una visión clara de lo que podemos llegar a tener en una página de opciones, te voy a mostrar unos ejemplos básicos para entender como se comportan las distintas funciones que nos proporciona WordPress de forma nativa.

Aprovecha el código, copia, pega y modifica los textos en función de tus necesidades. Cambia el nombre de las funciones, de los campos, de las páginas, añade otros campos y ponle estilos personalizados.

Creamos la Página Principal de Opciones

Este código crea una página personalizada en el panel de administración de WordPress, para que los administradores puedan gestionar configuraciones específicas del sitio desde el área de administración. Me adelanto y defino como se va a llamar el grupo de opciones donde irán los campos personalizados en este caso y sin darme mucho mal por el nombre es grupo_opciones este tiene que coincidir con los register_setting que vamos a ir introduciendo.

<?php
add_action('admin_menu', 'mi_pagina_de_opciones');

function mi_pagina_de_opciones() {
    add_menu_page(
        'Configuración General', // Título de la página
        'Opciones Generales',    // Texto del menú
        'manage_options',        // Capacidad requerida
        'opciones_generales',    // Slug único
        'render_pagina_general', // Función que renderiza el contenido
        'dashicons-admin-generic', // Icono del menú
        20                       // Posición del menú
    );
}

function render_pagina_general() {
    ?>
    <div class="wrap">
        <h1>Configuración General</h1>
        <form method="post" action="options.php">
            <?php
            settings_fields('grupo_opciones'); // Coincide con register_setting
            do_settings_sections('opciones_generales'); // Slug único de página de opciones
            submit_button();
            ?>
        </form>
    </div>
    <?php
}
  • admin_menu: Este hook indica que queremos ejecutar una función cuando WordPress está configurando el menú de administración.
  • add_menu_page(): Esta función de WordPress admite 7 parámetros (Título de la página, Texto que saldrá en el menú, Capacidades requeridas para roles de usuario, Slug, función para renderizar el contenido, icono y posición en el menú de WordPress).
  • form method="post" action="options.php": En el formulario que renderizamos method="post" define el método HTTP que se utilizará para enviar los datos al servidor. action="options.php" es un endpoint predeterminado de WordPress donde se procesan y guardan las opciones registradas. ¡IMPORTANTE! sin esto no se guardará el contenido en la base de datos.
  • settings_fields(): Registra los campos ocultos de seguridad (como el nonce) para el grupo de opciones identificado como 'grupo_opciones'.Este grupo debe coincidir con el definido en register_setting.
  • do_settings_sections(): Renderiza los campos y secciones asociados con la página identificada por el slug 'opciones_generales'.Los campos y secciones se registran mediante funciones adicionales como add_settings_section y add_settings_field. (Los vemos mas abajo)

Crearemos Subpáginas (Opcional)

El siguiente código extiende la funcionalidad del menú de administración de WordPress para añadir una subpágina dentro de una página principal. Esto es útil cuando deseas organizar diferentes secciones de configuración en un proyecto más grande. De nuevo hacemos referencia al grupo de opciones que esta página va a llevar llamandolo grupo_opciones_avanzadas.

<?php
add_action('admin_menu', 'mi_subpagina_de_opciones');

function mi_subpagina_de_opciones() {
    add_submenu_page(
        'opciones_generales',   // Slug de la página principal
        'Configuración Avanzada', // Título de la subpágina
        'Avanzado',             // Texto del submenú
        'manage_options',       // Capacidad requerida
        'configuracion_avanzada', // Slug único
        'render_pagina_avanzada' // Función que renderiza el contenido
    );
}

function render_pagina_avanzada() {
    ?>
    <div class="wrap">
        <h1>Configuración Avanzada</h1>
        <form method="post" action="options.php">
            <?php
            settings_fields('grupo_opciones_avanzadas'); // Coincide con register_sertting
            do_settings_sections('configuracion_avanzada'); // Slug único de subpágina
            submit_button();
            ?>
        </form>
    </div>
    <?php
}
  • admin_menu: Igual que en el caso anterior, este hook se utiliza para ejecutar una función (mi_subpagina_de_opciones) al momento de construir el menú de administración.
  • add_submenu_page(): Esta función de WordPress admite 6 parámetros (SLug de la página principal muy importante para asociar subpáginas con páginas, Título de la subpágina, texto para mostrar en el submenu, capacidad requerida para roles de usuario, Slug único y función para renderizar el contenido).

Registramos todos los campos personalizados necesarios

Ahora vamos a implementar campos personalizados para las dos páginas de opciones que hemos creado. Los vamos a registrar dentro de los grupos de opciones que ya hemos definido antes (grupo_opciones y grupo_opciones_avanzadas).

<?php
add_action('admin_init', 'registrar_campos_opciones');

function registrar_campos_opciones() {
    // Campo para la página principal
    register_setting('grupo_opciones', 'mi_campo_personalizado');
    add_settings_section(
        'seccion_general',
        'Ajustes Generales',
        null,
        'opciones_generales'
    );
    add_settings_field(
        'campo_personalizado',
        'Campo Personalizado',
        'render_campo_personalizado',
        'opciones_generales',
        'seccion_general'
    );

    // Campo para la subpágina
    register_setting('grupo_opciones_avanzadas', 'mi_campo_avanzado');
    add_settings_section(
        'seccion_avanzada',
        'Ajustes Avanzados',
        null,
        'configuracion_avanzada'
    );
    add_settings_field(
        'campo_avanzado',
        'Campo Avanzado',
        'render_campo_avanzado',
        'configuracion_avanzada',
        'seccion_avanzada'
    );
}

function render_campo_personalizado() {
    $valor = get_option('mi_campo_personalizado');
    echo '<input type="text" name="mi_campo_personalizado" value="' . esc_attr($valor) . '" />';
}

function render_campo_avanzado() {
    $valor = get_option('mi_campo_avanzado');
    echo '<input type="text" name="mi_campo_avanzado" value="' . esc_attr($valor) . '" />';
}
  • admin_init: Este hook se ejecuta cuando WordPress inicializa el panel de administración. Es el lugar indicado para registrar configuraciones, secciones y campos de opciones.
  • register_setting(): Esta función primero le indicamos el nombre del grupo al que pertenece esta configuración. Este debe coincidir con el grupo pasado a settings_fields en la página de opciones. Seguido añadimos el nombre de la opción que se guardará en la base de datos. WordPress almacenará esta opción en la tabla wp_options.
  • add_setting_section(): Crea las secciones Ajustes Generales y Ajustes Avanzados para la página y subpágina identificadas con los slugs opciones_generales y configuracion_avanzada.
  • add_setting_field(): Añade los campos llamados campo_personalizado y campo_avanzado con sus respectivas funciones render_ para insertar el html y cualquier otro código que necesiten.
  • get_option(): Función para recupera el valor de la opción almacenada en la base de datos.
  • value="' . esc_attr($valor) . ' : Se utiliza para mostrar el contenido de la base de datos en el campo personalizado.

Registrar un campo Repeater

Hay un campo especial que nos gusta mucho incluir a los desarrolladores y este es el campo «repeater». Una de las razones para usar el plugin Advanced Custom Field PRO que lo hace muy bien.

Bien, ahora con el siguiente snippet podremos prescindir de este plugin, sobre todo si estamos desarrollando plugins o temas personalizados para WordPress, no queremos obligar a instalar o requerir de este plugin para que todo nuestro desarrolo funcione correctamente. Queda muy mal hacer eso.

Siguiendo la misma lógia de antes, este sería un ejemplo básico de un repeater de un solo campo de texto.

<?php
add_action('admin_init', 'registrar_repeater_opciones');

function registrar_repeater_opciones() {
    register_setting('grupo_opciones', 'mi_repeater');
    add_settings_section(
        'seccion_repeater',
        'Opciones Repeater',
        null,
        'opciones_generales'
    );
    add_settings_field(
        'campo_repeater',
        'Campo Repeater',
        'render_repeater',
        'opciones_generales',
        'seccion_repeater'
    );
}

function render_repeater() {
    $repeater_data = get_option('mi_repeater', []);
    echo '<div id="repeater-container">';
    if (!empty($repeater_data)) {
        foreach ($repeater_data as $index => $item) {
            echo '<div class="repeater-item">';
            echo '<input type="text" name="mi_repeater[' . $index . '][campo]" value="' . esc_attr($item['campo'] ?? '') . '" />';
            echo '<button class="remove-item">Eliminar</button>';
            echo '</div>';
        }
    }
    echo '</div>';
    echo '<button id="add-repeater-item">Añadir Item</button>';

    // JavaScript para manejar el repeater
    ?>
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const container = document.getElementById('repeater-container');
            const addButton = document.getElementById('add-repeater-item');
            addButton.addEventListener('click', (e) => {
                e.preventDefault();
                const index = container.children.length;
                const item = document.createElement('div');
                item.classList.add('repeater-item');
                item.innerHTML = `
                    <input type="text" name="mi_repeater[${index}][campo]" value="" />
                    <button class="remove-item">Eliminar</button>
                `;
                container.appendChild(item);
            });

            container.addEventListener('click', (e) => {
                if (e.target.classList.contains('remove-item')) {
                    e.preventDefault();
                    e.target.closest('.repeater-item').remove();
                }
            });
        });
    </script>
    <?php
}
  • admin_init: Este hook lo utilizaremos para inicializar y configurar la función en el área de administración.
  • register_setting(): IMPORTANTE referenciar el grupo de opciones donde queremos que se integre este campo.
  • Función render_repeater(): Devuelve un grupo de campos mas completo, al ser un repeater, necesitamos iterar todos los campos que lleve integrado el mismo. Además le incorporamos un script de Javascript el cual estará escuchando los eventos de los botones de añadir item o eliminar. Manipularemos el formulario con Javascript antes de guardar el contenido en la base de datos.
  • En el ejemplo cada item del repeater sólo lleva un campo de texto. Puedes añadirle tantos campos necesites.

¿Como mostramos el contenido en la web?

Para obtener y mostar los valores de los campos personalizados guardados en la base de datos, disponemos de la función nativa de WordPress get_option('mi_campo_personalizado');

Guardamos en variables los valores de los campos y utilizamos una función echo de PHP junto a una función para escapar el contenido e imprimimos estos valores en páginas, plantillas de página, shortcodes, secciones o donde nos permita introducir código PHP.

Los siguientes ejemplos son para imprimir campos de texto y el repeater que hemos creado antes.

<?php
// Extraer el contenido de un campo de texto
$mi_valor = get_option('mi_campo_personalizado');
echo esc_html($mi_valor);
<?php
// Extraer el contenido de un campo Repeater
$repeater_data = get_option('mi_repeater', []);
if (!empty($repeater_data)) {
    foreach ($repeater_data as $item) {
        echo esc_html($item['campo'] ?? '');
    }
}

Resultado

Así quedarán la pagina, subpágina y campos personalizados incluyendo el repeater. Es un tutorial básico el cual te invito a que completes tus páginas de opciones con todos los campos o información necesaria para tu proyecto.

Combina las opciones que te he ido contando, hay muchísimo contenido que puedes gestionar desde estas páginas que no te he contado desde (Coordenadas para mapas, conexiones con APIs externas, generadores de contraseñas, muestra logs de tu aplicación, añade gráficos con estadísticas, configura Google Analytics, implementa A/B Testing con variaciones de contenido, ofrece distintos diseños para un tema de WordPress por ejemplo, añade notificaciones…) Como ves hay infinitas posibilidades para extender tu proyecto.

Interfaz Página de opciones
Interfaz subpágina de opciones
Interfaz Campos Personalizados incluyendo Repeater

Espero que hayas entendido lo importante que es tener una buena página de opción, que hayas visto las infinitas combinaciones que posees para llevar tus desarrollos al siguiente nivel. Y ojalá puedas utilizar mis ejemplos para el día a día de tu trabajo, ayudandote a ganar tiempo de desarrollo.

Si aún te has quedado con ganas de saber algo más, házmelo saber desde la parte de comentarios.

Seguiré compartiendo para que sigas aprendiendo cosas nuevas.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *