WordPress termmeta

¿Quieres patrocinar?

¿Quieres aparecer aquí? Si quieres patrocinar este blog, ponte en contacto conmigo a través de este formulario

Guía sobre WordPress term meta

El lanzamiento de la versión de WordPress 4.4 está previsto para el próximo 8 de diciembre. Trae consigo muchas novedades entre las que se encuentran la REST API, las imágenes responsive, el nuevo tema twentysixteen…y (por fin) los termmeta!

¿Por qué digo que por fin? La funcionalidad de poder enriquecer los terms de WordPress con metadatos es algo que se espera desde hace mucho tiempo, de hecho el ticket original para esta petición se abrió hace 6 años. Y por fin, se incluye en la nueva versión.

No obstante, cierto es que podíamos suplir esta carencia con el uso de plugins (yo personalmente utilizaba Advanced Custom Fields), pero que a partir de ahora esté incluido en el core de WordPress es una gran noticia para los desarrolladores de temas y plugins.

¿Qué es termmeta?

Los terms son los elementos pertenecientes a una taxonomía. ¿Y que es una taxonomía? Una taxonomía es un sistema para categorizar o clasificar los posts (o post-type). Por defecto WordPress incluye dos taxonomías para los posts: Categorías y Etiquetas. Y los elementos de cada taxonomía son los terms.

Tras esta breve introducción, podemos entender que termmeta es toda la información adicional que podemos agregar a un term determinado. Actualmente tenemos esta misma funcionalidad para los posts, con los postmeta, donde podemos agregar información adicional al post. Y también para los usuarios: users y usermeta, y para los comentarios: comments y commentmeta.

Ahora quizá se entienda un poco más el ¡por fin! Hasta ahora podíamos extender campos personalizados a posts, usuarios y comentarios, pero no para los terms, excepto si usábamos algún plugin.

En la vida real, ¿para qué nos pueden ser útil los termmeta?

La meta información de la manera que está planteada en WordPress, te permite agregar cualquier dato adicional a un objeto determinado. Es decir, guardaremos en la base de datos un par clave/valor relacionado con el ID de un objeto concreto.

De ésta manera no tienes límite a la hora de agregar información extra en función de tus necesidades. A continuación sólo una pequeña muestra de algunas ideas que nos pueden ser útiles para dotar a nuestros terms de información adicional:

  • Imagen destacada
  • Icono
  • Color
  • Campos para hacer SEO personalizado
  • Asignar templates específicos para categorías determinadas
  • Asignar un orden
  • Marcar un term como privado

¿Cómo usar termmeta?

WordPress incluye nuevas funciones para el tratamiento (añadir, modificar, obtener y borrar) de los termmeta. Si estás familiarizado con los post, comment o user meta, te resultará muy fácil entenderlas. Estas nuevas funciones son: add_term_meta(), update_term_meta(), delete_term_meta() y get_term_meta().

Vamos a ver con un ejemplo práctico cómo añadir a las categorías una imagen destacada, y 3 campos adicionales para realizar un SEO personalizado. El primer paso es añadir los nuevos campos al formulario de añadir y editar categorías. Para ello tenemos dos hooks:

  • {$taxonomy}_add_form_fields, para el formulario de añadir nuevo
  • {$taxonomy}_edit_form_fields, para el formulario de editar

En nuestro ejemplo, vamos a añadirlos a la taxonomía Category. Los formularios de añadir nueva taxonomía y editar taxonomía poseen diferente estructura HTML, por lo tanto tenemos que dividir en dos funciones la carga de nuestros nuevos campos. Añadiremos en nuestro functions.php:

<?php

//Función para añadir campos personalizados al formulario de Añadir nueva taxonomía
function my_category_addform_termmeta() {
  wp_nonce_field( 'my_category_termmeta', 'my_category_termmeta_nonce' );?>

  <div class="form-field category-image-wrap">
    <label for="category-image">Imagen destacada</label>
    <div class="custom_media_item">
      <a href="#" class="button button-primary custom_media_item_upload">Subir imagen</a>
      <input type="hidden" id="category-image" name="category-image" value="" />
      <img src="" style="max-width:150px;display:none;" />
      <a href="#" class="button button-primary custom_media_item_delete" style="display:none;">Eliminar</a>
    </div>
  </div>

  <div class="form-field seo-meta-title-wrap">
    <label for="seo-meta-title">SEO Meta Title</label>
    <input type="text" id="seo-meta-title" name="seo-meta-title" value="" />
  </div>

  <div class="form-field seo-meta-description-wrap">
    <label for="seo-meta-description">SEO Meta Description</label>
    <textarea id="seo-meta-description" name="seo-meta-description" rows="4"></textarea>
  </div>

  <div class="form-field seo-meta-keywords-wrap">
    <label for="seo-meta-keywords">SEO Meta Keywords</label>
    <input type="text" id="seo-meta-keywords" name="seo-meta-keywords" value="" />
  </div>
<?php }
add_action( 'category_add_form_fields', 'my_category_addform_termmeta' );


//Función para añadir campos personalizados al formulario de Editar taxonomía
function my_category_editform_termmeta( $term ) {
  $category_image = get_term_meta( $term->term_id, 'category-image', true );
  $seo_meta_title = get_term_meta( $term->term_id, 'seo-meta-title', true );
  $seo_meta_description = get_term_meta( $term->term_id, 'seo-meta-description', true );
  $seo_meta_keywords = get_term_meta( $term->term_id, 'seo-meta-keywords', true );

  wp_nonce_field( 'my_category_termmeta', 'my_category_termmeta_nonce' );?>

  <tr class="form-field category-image-wrap">
    <th scope="row"><label for="category-image">Imagen destacada</label></th>
    <td>
      <div class="custom_media_item">
        <?php
        $display = "";
        if (empty($category_image) || $category_image == "") { $display = 'display:none';}
        $media_item_src = wp_get_attachment_url( $category_image );?>

        <a href="#" class="button button-primary custom_media_item_upload">Subir imagen</a>
        <input type="hidden" id="category-image" name="category-image" value="<?php echo $category_image;?>" />
        <img src="<?php echo $media_item_src;?>" style="max-width:150px;<?php echo $display;?>" />
        <a href="#" class="button button-primary custom_media_item_delete" style="<?php echo $display;?>">Eliminar</a>
      </div>
    </td>
  </tr>
  <tr class="form-field seo-meta-title-wrap">
    <th scope="row"><label for="seo-meta-title">SEO Meta Title</label></th>
    <td>
      <input type="text" id="seo-meta-title" name="seo-meta-title" value="<?php echo sanitize_text_field($seo_meta_title);?>" />
    </td>
  </tr>
  <tr class="form-field seo-meta-description-wrap">
    <th scope="row"><label for="seo-meta-description">SEO Meta Description</label></th>
    <td>
      <textarea id="seo-meta-description" name="seo-meta-description" rows="4"><?php echo sanitize_text_field($seo_meta_description);?></textarea>
    </td>
  </tr>
  <tr class="form-field seo-meta-keywords-wrap">
    <th scope="row"><label for="seo-meta-keywords">SEO Meta Keywords</label></th>
    <td>
      <input type="text" id="seo-meta-keywords" name="seo-meta-keywords" value="<?php echo sanitize_text_field($seo_meta_keywords);?>" />
    </td>
  </tr>
<?php }
add_action( 'category_edit_form_fields', 'my_category_editform_termmeta' );

Ahora vamos a enlazar el botón de añadir imagen destacada para la categoría con la librería multimedia. Agregaremos en nuestro functions.php:

<?php

function my_admin_scripts(){
  //Agregamos nuestro JS
  wp_enqueue_script( 'my_custom_fields_js', get_template_directory_uri() . '/js/custom-fields.js', array('jquery'), '1.0' );

  //Añadimos la librería multimedia
  wp_enqueue_media();
}
add_action( 'admin_print_scripts', 'my_admin_scripts' );

Como se puede ver, hemos incluido el archivo custom-fields.js en nuestro admin. Dentro de este archivo enlazamos nuestro botón de subir imagen con la librería multimedia:

jQuery(document).ready(function ($) {
  $('.custom_media_item_upload').on("click", function() {
    var send_attachment_bkp = wp.media.editor.send.attachment;
    var button = $(this);

    wp.media.editor.send.attachment = function(props, attachment) {
      $(button).next().val(attachment.id);
      $(button).next().next().attr('src', attachment.url);
      $(button).next().next().show();
      $(button).next().next().next().show();

      wp.media.editor.send.attachment = send_attachment_bkp;
    }
    wp.media.editor.open(button);

    return false;       
  });

  $('.custom_media_item_delete').on("click", function() {
    var button = $(this);

    $(button).hide();
    $(button).prev().attr('src', '');
    $(button).prev().hide();
    $(button).prev().prev().val('');

    return false;       
  });
});

Por último falta salvar los metadatos cuando añadamos o editemos una categoría. Para esta acción usaremos los hooks create_{$taxonomy} y edit_{$taxonomy}. Afortunadamente en esta ocasión nos servirá la misma función:

<?php

function my_category_fields_save_data( $term_id ) {
  // Comprobamos si se ha definido el nonce.
  if ( ! isset( $_POST['my_category_termmeta_nonce'] ) ) {
    return $term_id;
  }
  $nonce = $_POST['my_category_termmeta_nonce'];
      
  // Verificamos que el nonce es válido.
  if ( !wp_verify_nonce( $nonce, 'my_category_termmeta' ) ) {
    return $term_id;
  }

  // Si existen entradas antiguas las recuperamos
  $old_category_image = get_term_meta( $term_id, 'category-image', true );
  $seo_meta_title = get_term_meta( $term_id, 'seo-meta-title', true );
  $seo_meta_description = get_term_meta( $term_id, 'seo-meta-description', true );
  $seo_meta_keywords = get_term_meta( $term_id, 'seo-meta-keywords', true );

  // Saneamos lo introducido por el usuario.
  $category_image = sanitize_text_field( $_POST['category-image'] );
  $seo_meta_title = sanitize_text_field( $_POST['seo-meta-title'] );
  $seo_meta_description = sanitize_text_field( $_POST['seo-meta-description'] );
  $seo_meta_keywords = sanitize_text_field( $_POST['seo-meta-keywords'] );

  // Actualizamos el campo meta en la base de datos.
  update_term_meta( $term_id, 'category-image', $category_image, $old_category_image );
  update_term_meta( $term_id, 'seo-meta-title', $seo_meta_title, $old_seo_meta_title );
  update_term_meta( $term_id, 'seo-meta-description', $seo_meta_description, $old_seo_meta_description );
  update_term_meta( $term_id, 'seo-meta-keywords', $seo_meta_keywords, $old_seo_meta_keywords );
}
add_action( 'edit_category', 'my_category_fields_save_data' );
add_action( 'create_category', 'my_category_fields_save_data' );

Con esto ya tenemos la funcionalidad completa para agregar campos adicionales a nuestras categorías. Vamos ahora a ir un poco más allá, y añadiremos al listado de categorías la imagen destacada que hemos adjuntado, para ver de un vistazo las imágenes que vayamos asociando a cada categoría. Añadiremos a nuestro functions.php:

<?php

function my_custom_category_columns( $columns ) {
  $columns['featured_image'] = "Imagen";

  return $columns;
}
add_filter( 'manage_edit-category_columns', 'my_custom_category_columns' );

function my_category_image_column( $out, $column, $term_id ) {
  if ( $column === 'featured_image' ) {
    $category_image = get_term_meta( $term_id, 'category-image', true );
      if (!empty($category_image)) {
        $media_item_src = wp_get_attachment_image_src( $category_image, "thumbnail" );
        $return = sprintf( '<img src="%s" width="64">', $media_item_src[0] );
      }
    }

  return $return;
}
add_filter( 'manage_category_custom_column', 'my_category_image_column', 10, 3 );
campos personalizados categorias

Esto sólo es un ejemplo de cómo enriquecer una taxonomía concreta mediante el uso de metadatos. Después en nuestro front podremos recuperar esta información y usarla para dar formato, destacar o añadir información adicional a nuestras categorías.

¿Te ha resultado útil esta información?

Si este post te ha resuelto un problema, invítame a un café o a una cerveza. Con este pequeño gesto me animas a seguir escribiendo.