Grabar custom post type desde el frontend de WordPress

Grabar un Custom Post Type desde el frontend de WordPress facilita a los usuarios de tu web el introducir información en el sitio sin tener que acceder al escritorio de WordPress.

En el artículo Cómo crear tipos y campos personalizados en WordPress veías que sencillo es crear un Custom Post Type desde un plugin. Con ese sistema los usuarios pueden acceder al escritorio de WordPress y crear nuevos ítems utilizando ese CPT.

El problema se plantea si no quieres que los usuarios accedan al escritorio para crear estos contenidos, la solución es un formulario que puedes crear y procesar de una manera relativamente simple. En este artículo verás como puedes hacerlo sin utilizar plugin de terceros.

Los elementos más importantes son los siguientes:

  • Crear el formulario con un shortcode para mostrarlo en una página, una entrada o un widget.
  • El formulario llama desde el «action» a admin-post.php
  • Registrar los hooks admin_post{$action} y admin_post_nopriv{$action} para poder grabar desde usuarios autenticados y no autenticados
  • En la función asociada a estos hooks preparar el array con la información del CPT que viene del formulario y grabar con la función wp_insert_post($args)

Y en los detalles está el diablo:

  • Redirigir de nuevo a la URL actual después de grabar para mostrar algún feedback al usuario
  • Prefijar todos los campos del formulario para evitar conflictos
  • Filtrar bien las entradas y utilizar un campo nonce para evitar problemas de seguridad.

Para este ejemplo vas a crear un Custom Post Type de manera que los lectores de un blog puedan proponer ideas para la creación de nuevos artículos o los usuarios de una aplicación puedan proponer características que les gustaría ver implementadas. La gracia es que estas ideas puedan ser propuestas directamente desde un formulario y se pueden dar por publicadas directamente o dejarlas como borradores. En una segunda versión de este plugin los usuarios podrán votar cada idea para que se escriba o implemente primero la que obtenga más votos.

En el artículo cómo programar un formulario sin plugins explico las bases para crear un plugin de una manera detallada, así que aquí voy al grano. Lo haré todo en un sólo fichero para que tengas una mejor visión de conjunto , estas serían las primeras líneas del plugin donde hago las llamadas a los hooks para:

  • Crear el Custom Post Type
  • Agregar el shortcode que permite mostrar el formulario en una página o entrada.
  • Definir la función que procesará el formulario cuando se pulsa el botón de Enviar
<?php
/**
 * Plugin Name: KFP Grabar CPT Frontend
 * Description: Plugin de ejemplo para el artículo "Grabar Custom Post Type desde el frontend de WordPress". Utiliza el shortcode [kfp_gcf_form_idea]
 * Author: KungFuPress
 * Author URI: https://kungfupress.com
 * Version: 0.1
 */
 
// Evita que se llame directamente a este fichero sin pasar por WordPress
defined( 'ABSPATH' ) or die();
// Crea el CPT al activar el plugin
add_action('init', 'kfp_cpt_idea', 10);
// Crea el shortcode para mostrar el formulario de propuesta de ideas
add_shortcode('kfp_gcf_form_idea', 'Kfp_Gcf_Form_idea');
// Agrega los action hooks para grabar el formulario (el primero para usuarios 
// logeados y el otro para el resto)
// Lo que viene tras admin_post_ y admin_post_nopriv_ tiene que coincidir con 
// el value del campo input con name "action" del formulario
add_action("admin_post_kfp-gcf-grabar-idea", "Kfp_Gcf_Grabar_idea");
add_action("admin_post_nopriv_kfp-gcf-grabar-idea", "Kfp_Gcf_Grabar_idea");

A continuación tienes la función que crea el CPT, he reducido la configuración a la mínima expresión, si necesitas algo más elaborado puedes consultar la documentación oficial o utilizar Post Type Generator para que te lo haga a medida

/**
 * Crea el CPT Idea con lo mínimo que se despacha en CPT
 *
 * @return void
 */
function kfp_cpt_idea()
{
    $args = array(
        'public' => true,
        'label'  => 'Ideas'
      );
      register_post_type('idea', $args);
}

Sigue con la función que pintará el formulario de entrada allá donde pongas el shortcode [kfp_gcf_form_idea].

Fíjate en la URL del action del formulario, que llama a admin_post.php y en el input oculto con nombre action y valor kfp-gcf-grabar-idea que será el que activará el hook correspondiente admin_post_kfp-gcf-grabar-idea o admin_post_nopriv_kfp-gcf-grabar-idea. También he puesto un campo oculto que almacena la URL actual para que al procesar el formulario vuelva de nuevo a la misma página o entrada.

/**
 * Muestra el formulario para proponer ideas desde el frontend
 *
 * @return void
 */
function Kfp_Gcf_Form_idea()
{
    if (isset($_GET['kfp_gcf_texto_aviso'])) {
        echo "<h4>" . $_GET['kfp_gcf_texto_aviso'] . "</h4>";
    }
    ob_start();
    ?>
    <form name="idea"action="<?php echo esc_url(admin_url('admin-post.php')); ?>"
        method="post" id="kfp-gcf-form-grabar-idea">
        <?php wp_nonce_field('kfp-gcf-form', 'kfp-gcf-form-nonce'); ?>
        <input type="hidden" name="action" value="kfp-gcf-grabar-idea">
        <input type="hidden" name="kfp-url-origen"
            value="<?php echo home_url( add_query_arg(array())); ?>"
        <p>
            <label for="kfp-gcf-title">Idea</label>
            <input type="text" name="kfp-gcf-title" id="kfp-gcf-title"
                placeholder="Pon un título breve pero descriptivo a tu idea">
        </p>
        <p>
            <label for="kfp-gcf-content">Descripción</label>
            <textarea name="kfp-gcf-content" id="kfp-gcf-content"
                placeholder="Aquí puedes explicar mejor tu idea"></textarea>
        </p>
        <p>
            <input type="submit" name="kfp-gcf-submit" value="Enviar idea">
        </p>
    </form>
    <?php
    return

El formulario podría quedar más o menos así en tu web:

Formulario para grabar custom post type desde el frontend con los campos "Idea" y "Descripción"

Y por último la función que graba la nueva «idea» con los contenidos del formulario. Es un poco larga porque los avisos quedan muy aparatosos, pero lo más importante aquí es asignar los valores a los campos del CPT y luego grabarlos con la función wp_insert_post()

/**
 * Procesa el formulario para proponer ideas desde el frontend
 *
 * @return void
 */
function Kfp_Gcf_Grabar_idea()
{
    if (filter_has_var(INPUT_POST, 'kfp-url-origen')) {
        $url_origen = filter_input(INPUT_POST, 'kfp-url-origen', FILTER_SANITIZE_URL);
    }
 
    if(empty($_POST['kfp-gcf-title']) || empty($_POST['kfp-gcf-content'])
        || !wp_verify_nonce($_POST['kfp-gcf-form-nonce'], 'kfp-gcf-form')) {
        $aviso = "error";
        $texto_aviso = "Por favor, rellena los contenidos requeridos del formulario";
        wp_redirect(
            esc_url_raw(
                add_query_arg(
                    array(
                        'kfp_gcf_aviso' => $aviso,
                        'kfp_gcf_texto_aviso' => $texto_aviso,
                    ),
                    $url_origen
                ) 
            ) 
        );
        exit();
    }
 
    $args = array(
        'post_title' => filter_input(INPUT_POST, 'kfp-gcf-title', FILTER_SANITIZE_STRING),
        'post_content' => filter_input(INPUT_POST, 'kfp-gcf-content', FILTER_SANITIZE_STRING),
        'post_type' => 'idea',
        'post_status' => 'draft',
        'comment_status' => 'closed',
        'ping_status' => 'closed'
    );
 
    // Esta variable $post_id contiene el ID del nuevo registro 
    // Vendría de perlas para grabar los metadatos
    $post_id = wp_insert_post($args);
 
    $aviso = "success";
    $texto_aviso = "Has registrado tu idea correctamente. ¡Gracias!";
    wp_redirect(
        esc_url_raw(
            add_query_arg(
                array(
                    'kfp_gcf_aviso' => $aviso,
                    'kfp_gcf_texto_aviso' => $texto_aviso,
                ),
                $url_origen
            ) 
        ) 
    );
    exit();
}

Bueno, espero que no te hayas perdido por el camino, los tres pasos fundamentales para grabar un Custom Post Type desde el frontend han sido:

  • Crear el CPT al activar el plugin
  • Pintar el formulario cuando utilices el shortcode
  • Grabar la nueva «idea» en la base de datos de WordPress

Tienes el código completo de este pequeño plugin en GitHub

Coméntame que te ha parecido este artículo y si le ves utilidad en alguno de tus desarrollos. Si te gusta la «idea» en posteriores artículos puedo desarrollarla un poco más:

  • Grabando metadatos del CPT
  • Permitir la escritura sólo a usuarios autenticados, por ejemplo para un membership.
  • Desarrollando el sistema que permite votar las ideas de otros usuarios.

En cualquier caso espero tener pronto el desarrollo completo de este tema en el curso de desarrollo de plugins que estoy preparando. Puedes suscribirte a la lista de correos para estar al tanto de las novedades.