Creando taxonomías personalizadas, con campos personalizados y en publicaciones personalizadas en WordPress

Aprende a crear taxonomías personalizadas, agregarle campos personalizados y asignarlos en publicaciones personalizadas todo en WordPress de forma fácil

Si has llegado aquí es porque estás buscando cómo diantres hacerle para crear taxonomías personalizadas (custom taxonomies/taxonomy) y aunque el título no lo pude reducir (o quizá no quise por SEO(?)), vamos a ver no solo cómo crear esas taxonomías personalizadas, si no agregarles un campo especial, mostrarlo en la tabla de esta, mostrar la taxonomía personalizada en un menú y agregarle estas taxonomías personalizadas a un tipo de publicación personalizado (o custom post en inglés) todo en WordPress.

Como es costumbre, daré el contexto, ¿por qué alguien querría esto?. Bueno vamos a pensar que tenemos un tipo de publicación personalizada, vamos a decirle “Menú”. En este tipo de post (de aquí en adelante usaremos los términos en inglés, no es mi costumbre pero así es como se llaman entonces para mejor referencia), vamos a agregarle el tipo de “Menú” para por ejemplo relacionar que un menú es para “A la carta” o “Servicio a la habitación”.

¡Pero eso no es todo!, ¿y si queremos agregarle un campo personalizado a la publicación y a la taxonomía?, eso también lo veremos…

Muchas veces muchos usuarios de WordPress son usuarios no-desarrolladores y se ponen a instalar plugins como “Advanced Custom Fields” y cosas así, pero muchos como desarrolladores sabemos que si ocupamos algo específico y a la vez que no agregue peso innecesario y complejidad preferimos hacerlo nosotros y simplificarlo, así que todo aquí será hecho con código.

El archivo functions.php…

Lo primero a tener en cuenta es el archivo functions.php que es donde estaremos agregando la gran mayoría de nuestro código.

*** Aviso ***

Para cada función que estaremos agregando aquí, se debe agregar el siguiente código (a menos que se explique lo contrario):

add_action('init', 'nombreDeLaFuncion');

Y ojo, normalmente WordPress recomienda usar nombre_de_la_funcion pero a mi no me gusta, así que al gusto de cada quién y lo más importante… deben reemplazar nombreDeLaFuncion por el nombre de cada función que vamos agregando aquí abajo…

Para empezar, vamos a crear nuestro “custom post”, para ello, vamos a usar el siguiente código:

function registerCustomPostTypes()
{
    register_post_type('menu-post', [
        'labels' => [
            'name' => 'Menú',
            'singular_name' => 'Menu'
        ],
        'public' => true,
        'show_ui' => true,
        'show_in_menu' => true,
        'rewrite' => [
            'slug' => 'menu',
            'with_front' => false
        ],
        'supports' => ['title', 'thumbnail', 'editor'],
        'hierarchical' => false,
        'menu_icon' => 'dashicons-food',
    ]);
}

Esto lo que hace, como su nombre lo dice es registrar nuestro tipo de post personalizado, y esto lo integramos en una función (por si después quieren agregar más tipos de posts o mover este código a otro archivo e importarlo o cosas así… es decisión suya, nosotros lo hacemos solo como ejemplo).

Notemos algunas cosas aquí:

  • Se va a agregar al menú lateral dentro de la barra del administrador de WordPress gracias a su “show_in_menu”
  • Se agrega su nombre como “Menú” y su ícono como “dashicons-food”
  • No es “jerárquico” es decir no tiene “sub-temas”.
  • Soporta de base, el título, una imagen y el editor (para ponerle una descripción y cosas así).
  • Se llama “menu-post” nuestro post personalizado.

A grandes rasgos, esto es lo que nos permite entonces, tener nuestro tema personalizado y así se vería.

Ahora, ya que lo tenemos, vamos a agregarle el “Tipo de menú” (osea, nuestro custom taxonomy):

function registerCustomTaxonomies()
{
    register_taxonomy('menu-type', 'menu-post', [
        'hierarchical' => true,
        'labels' => [
            'name' => 'Tipo de Menú',
            'singular_name' => 'Tipo de Menú',
            'search_items' => 'Buscar Tipo de Menú',
            'all_items' => 'Todos los Tipos de Menú',
            'edit_item' => 'Editar Tipo de Menú',
            'update_item' => 'Actualizar Tipo de Menú',
            'add_new_item' => 'Agregar nuevo Tipo de Menú',
            'new_item_name' => 'Nuevo Tipo de Menú',
            'menu_name' => 'Tipo de Menú',
        ],
        'rewrite' => [
            'slug' => 'menu-type',
        ],
        'show_admin_column' => true,
        'show_in_rest' => true,
        'show_ui' => true,
        'query_var' => true,
    ]);
}

En este código, vamos a considerar los labels (el texto que se muestra) para la barra administrativa y los mensajes internos de botones y titulares, así como unas cosas extras:

  • Es jerárquico, porque cuando no lo es, se ve raro el selector y deben escribir algo ahí en vez de aparecer los checkboxes, así que por UX (de forma personal) lo dejamos así.
  • Se muestra dentro de la barra lateral con show_in_rest y en la barra del administrador.
  • Podemos ver el segundo parámetro de register_taxonomy en este caso puede ser un arreglo (array) o una cadena de caracteres (string), si por ejemplo quisiéramos que se permita esto no solo en la taxonomía sino también en las publicaciones normales o páginas podemos agregar algo como ['post', 'page', 'menu-post'] por poner un ejemplo, en este caso solo se lo aplicaremos al taxonomy.
  • Y le nombramos menu-type .

Ahora veríamos algo como:

Ignoren la taxonomía de “Categoría del Alimento o Bebida” 😛 es parte de un proyecto que trabajo justamente y ya saben que me gusta compartir con ustedes.

Y ya podemos ir agregando algunas…

¿Fácil no?… ¿pero cómo se ve en la barra lateral en la publicación?

¡Listo!, fácil, rápido tenemos un custom taxonomy, un custom post…¿qué sigue?.

Vamos a agregarle al custom post un input personalizado, como el precio del menú, ¿no?, entonces buscaríamos algo como esto:

Para ello, vamos a agregar algo llamado metabox en WordPress o “cajas meta” en español (qué feo suena)

Para ello vamos a agregar otra función.

function registerCustomInputs()
{
    add_meta_box(
        'price',
        'Precio',
        'showPriceInput',
        'menu-post',
        'normal',
        'high'
    );
}

En este caso se agregará de la siguiente forma:

add_action('add_meta_boxes', 'registerCustomInputs');

Esto mostraría la barra que nos permitirá agregar el input pero sin el input (o campo de texto)… para ello agreguemos entonces esa funcionalidad (ojo, antes de continuar nota que el nombre de la función es parte de los parámetros, en específico el tercero que se llama “callback” y el cuarto que es relacional al custom post, el primero es su “llave” y los demás podemos ignorarlos):

function showPriceInput()
{
    global $post;
    $metaPrice = get_post_meta($post->ID, 'price', true);
    ?>
    <input type="hidden" name="custom_metabox_menu" value="<?php echo wp_create_nonce(basename(__FILE__)); ?>">
    <label for="price">
        <input type="number" name="price" required placeholder="Precio (números solamente)" id="price"
               style="width: 100%;"
               value="<?php echo $metaPrice === '' ? 0 : $metaPrice; ?>"/>
    </label>
<?php 
}

Ojo aquí, esta función hace un cierre de etiqueta PHP ?> como se ve en la línea 5 de este código y al final se reabre, esto para poder mostrar mejor el HTML. Aunque creo que podría ser mejor….

Ahora expliquemos un poco esto, primero obtenemos el valor de la meta si es que existe claro y si no pues, mostrar “0”. Agregamos un nonce (algo así como una key “única”) que es un valor para evitar que haya CSRF o cosas raras. Y todo en su label con su placeholder y todo.

Ya debe verse como lo superior pero falta algo… agregar el que se guarde ese valor…

function saveCustomInputs($postId)
{
    if (!wp_verify_nonce($_POST['custom_metabox_menu'], basename(__FILE__))) {
        return $postId;
    }

    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
        return $postId;
    }

    if ('menu-post' === $_POST['post_type']) {
        if (!current_user_can('edit_page', $postId)) {
            return $postId;
        } elseif (!current_user_can('edit_post', $postId)) {
            return $postId;
        }
    }

    $oldPrice = get_post_meta($postId, 'price', true);
    $newPrice = sanitize_text_field($_POST['price']);

    if (!is_numeric($newPrice)) {
        return $postId;
    }

    if ($newPrice && $newPrice !== $oldPrice) {
        update_post_meta($postId, 'price', $newPrice);
    } elseif ('' === $newPrice && $oldPrice) {
        delete_post_meta($postId, 'price', $oldPrice);
    }

    return $postId;
}

Aquí lo que hacemos a grandes rasgos es verificar que se mande el nonce si no, pues “le damos continuidad”, si está en modo “AUTOGUARDADO” también le pasamos, no tenemos por qué guardar este dato hasta que de verdad no lo requerimos ya que no es parte del “borrador”.

Luego validamos que este campo SOLO se guarde si nuestro tipo de post es “menu-post” (que es el post personalizado que creamos antes). Antes de hacer la actualización o el guardado, validamos que sí sea un número (esto se puede saltar obvio en otros que no sean así, pero aunque el front lo valide, siempre el back debe revalidar), y ahora sí, si viene el campo y el precio es diferente, se actualiza, si no viene, lo borramos. Aunque muchos dirán “si no viene, que se quede el anterior”, eso es a gusto del cliente.

Se agrega de la siguiente forma:

add_action('save_post', 'saveCustomInputs');

Y eso es todo, ya podemos guardar estos campos personalizados del custom post 😉 ahora… ¿qué más falta?, el campo personalizado dentro del custom taxonomy.

Para esto vamos a crear un input para edición y otro para creación, vamos a nombrarle “Orden”:

function addCustomInputOnTaxonomy($taxonomy)
{
    ?>
    <div class="form-field">
        <label for="order">Orden</label>
        <input type="text" name="order" id="order"/>
        <p>El 1 es mayor orden, el 2 menor y así sucesivamente.</p>
    </div>
    <?php
}

function editCustomInputOnTaxonomy($term, $taxonomy)
{
    $orderField = get_term_meta($term->term_id, 'order', true);
    ?>
    <tr class="form-field">
        <th><label for="order">Orden</label></th>
        <td>
            <input name="order" id="order" type="text" value="<?php echo esc_attr($orderField) ?>"/>
            <p>El 1 es mayor orden, el 2 menor y así sucesivamente.</p>
        </td>
    </tr>
    <?php
}

Esto es bastante sencillo, mismo caso noten los <?php y ?> internos, ustedes pueden retirarlos.

Solo nos permite algo así como agregar cuál “tipo de menú” tiene mayor prioridad para mostrar “primero el menú A o el menú B”… Y como previamente se menciona, obtenemos el term del meta que vamos a crear (aún no agregamos esta funcionalidad en sí, lo haremos en el siguiente paso) para mostrar el guardado en la edición.

Para esto vamos a agregarlos en un método especial:

add_action('menu-type_add_form_fields', 'addCustomInputOnTaxonomy');
add_action('menu-type_edit_form_fields', 'editCustomInputOnTaxonomy', 10, 2);

Podemos notar que estos action empiezan con menu-type ahí se reemplaza con el nombre del custom taxonomy, si fuera por ejemplo food-category el custom taxonomy se vería así:

add_action('food-category_add_form_fields', 'addCustomInputOnTaxonomy');
add_action('food-category_edit_form_fields', 'editCustomInputOnTaxonomy', 10, 2);

Y listo, ahora ya tenemos dónde mostrar el input… y lo podemos ver así:

Ignoren la descripción, es parte del proyecto, el suyo se vería con lo anteriormente mencionado

Ahora vamos a incluir el guardar el campo personalizado en el custom taxonomy:

function saveCustomInputOnTaxonomy($termId)
{
    update_term_meta(
        $termId,
        'order',
        sanitize_text_field($_POST['order'])
    );
}

En este caso es sencillo, podemos agregar 2 pasos uno para validar si está establecido y otro si no, agregar más lógicas como la superior pero en este caso decidí reducirlo por ahora, ustedes deberán, como tarea, agregar esas validaciones.

Y se agrega de la siguiente forma:

add_action('created_menu-type', 'saveCustomInputOnTaxonomy');
add_action('edited_menu-type', 'saveCustomInputOnTaxonomy');

Como vemos dos cosas, es que ambos, edición y creación llaman a la misma función, pueden separar las lógicas si lo desean, y también noten el nombre de la custom taxonomy como menu-type así que ustedes deberán cambiarlo por el de su custom taxonomy.

Y se vería así en la edición como ejemplo (arriba esta la creación):

Por último, necesitamos mostrar esos valores en la tabla de la taxonomía personalizada:

function displayOrderOnTaxonomy($string, $columns, $term_id)
{
    switch ($columns) {
        case 'order' :
            echo esc_html(get_term_meta($term_id, 'order', true));
            break;
    }
}

function displayOrderOnTaxonomyColumn($columns)
{
    $columns['order'] = 'Orden';
    return $columns;
}

Y se agrega de la siguiente forma:

add_action('manage_food-category_custom_column', 'displayOrderOnTaxonomy', 10, 3);
add_filter('manage_edit-food-category_columns', 'displayOrderOnTaxonomyColumn');

Noten mismo caso menu-type como el taxonomy y que en este caso, podemos mostrar solo cuando es la columna order claro que podemos agregar otros más y solo mostrar el orden que es el que nos interesa. Por ejemplo, tenemos 3 campos y solo queremos que se vea este orden, solo ese mostramos…

Y se vería así:

¡Listo!

Para terminar, llamar los datos…

Con esto podemos ya utilizarlo donde queramos y llamar y hacer las lógicas que querramos por ejemplo:

get_post_meta($post->ID, 'price', true);

Y obtenemos el precio de un menú (basado en su ID)

get_term_meta($term->term_id, 'order', true);

Llamamos el orden del custom taxonomy basado en el ID de este.

$terms = wp_get_post_terms($post->ID, 'menu-type');

Llamamos las taxonomías creadas en el menu-type (o categorías como gusten llamarle) de un post

$loop = new WP_Query([
    'post_type' => 'menu-post',
    'posts_per_page' => -1,
    'post_status' => 'publish',
    'tax_query' => [[
        'taxonomy' => 'menu-type',
        'field' => 'slug',
        'terms' => 'room-service',
    ]],
    'orderby' => 'title',
    'order' => 'ASC'
])

Llamamos todos los posts del tipo personalizado menu-post y que tengan el taxonomy de menu-type con su “categoría” room-service (o servicio a la habitación)…

$categories = get_terms('menu-type');

Llamamos todos las categorías guardadas en el taxonomy menu-type y al final combinando todas estas cosas podemos obtener algo así:

Ignoren la falta de estilos 😅

¿Fácil no?.

Si te gustó el tutorial, no te olvides de dejar tu “Clap” y seguirme. ¡Nos vemos en el siguiente!

¿Cuál es tu reacción?
+1
0
+1
0
+1
0
+1
0
+1
0
Total
0
Shares
Publicación anterior

WordPress y el “usarlo para todo”

Siguiente Publicación

PHP and Mobile apps

Publicaciones Relacionadas