WordPress Metaboxes

Como desarrollador web, algunas veces he tenido que usar WordPress como framework y normalmente necesito configurar algunos post_types para cumplir los requerimientos de los clientes. Para no-desarrolladores esto es muy útil porque te permite crear contenido separando publicaciones normales de portfolio, equipo, libros o cualquier cosa que se te ocurra.

Entonces, ¿qué son los metaboxes?

Metaboxes son elementos de pantalla flexibles y modulares que pueden ser usados para almacenar información relacionada con el post que está siendo editado. Luego puedes obtener esa información en tu plantilla mediante la función get_post_meta.

Sin embargo esta tarea es un poco difícil la primera vez que intentas implementarlo, por esa razón intentaré explicar el proceso de una manera más sencilla que la Documentación de WordPress.

Configurando el post type

El primer paso es crear nuestro tipo de post dónde luego vamos a añadir el metabox. Como muchas veces necesitamos añadir más de 1 post_type a nuestro proyecto, me gusta añadirlos a un array y luego los recorro con la función register_post_type().

En este ejemplo voy a crear un tipo de post book con etiquetas de nombre personalizadas, archivo, taxonomías y slug. Este código debe estar en tu archivo functions.php de la plantilla.

add_action( 'init', 'create_post_types' );
function create_post_types() {
    $post_types = [];

    $post_types['book'] = array(
        'labels' => array(
          'name' => __( 'Books', 'child-theme' ),
          'singular_name' => __( 'Book', 'child-theme' ),
          'add_new' => __('Add new', 'child-theme'),
          'add_new_item' => __('Add new Book', 'child-theme' ),
          'edit_item' => __('Edit Book', 'child-theme' ),
          'new_item' => __('New Book', 'child-theme' ),
          'view_item' => __('View Book', 'child-theme' ),
          'view_items' => __('View Books', 'child-theme'),
          'search_items' => __('Search Book', 'child-theme'),
          'not_found' => __('No Books found', 'child-theme'),
          'not_found_in_trash' => __('No Books found in Trash', 'child-theme'),
          'all_items' => __('All Books', 'child-theme'),
          'archives' => __('Book Archives', 'child-theme'),
          'attributes' => __('Book Attributes', 'child-theme'),
        ),
        'public'             => true,
        'description'        => __('Books written by author', 'child-theme'),
        'publicly_queryable' => true,
        'show_ui'            => true,
        'show_in_menu'       => true,
        'query_var'          => true,
        'rewrite'            => array( 'slug' => 'book' ),
        'has_archive'        => true,
        'hierarchical'       => true,
        'menu_position'      => 5,  // Choose menu order (5 after Posts)
        'menu_icon'          => 'dashicons-book',
        'supports'           => array( 'title', 'editor', 'author', 'thumbnail', 'comments'),
        'taxonomies'         => array( 'category', 'tags' ),
        'capability_type'    => 'post',
        'map_meta_cap'       => true
    );

    foreach($post_types as $name => $args ) {
        register_post_type( $name, $args );
    }
}

Descripción de las principales opciones:

  • labels: Añade texto personalizado como el nombre tipo de post y campos del dashboard
  • rewrite: Configura tu propia url o slug para las páginas y archivos
  • menu_icon: Te permite personalizar el icono del dashboard desde WordPress Dashicons
  • supports: WordPress soporta algunos campos por defecto como editor, thumbnail, comentarios o excerpt. Más info
  • capability_type: Puedes pasar un array para luego establecer los permisos array('book', 'books'), o simplemente escribe "post" para abstraer los permisos por defecto en este post_type.

Books Post Type

Archivos de plantilla

Las vistas de archivos (listados) y páginas pueden personalizarse siguiendo la estructura de plantillas WordPress.

  • Los posts individuales usarán single-{post_type}.php
  • Los archivos usarán archive-{post_type}.php

Ahora que nuestro tipo de post personalizado está creado vamos a añadirle un metabox.

Campos de Metabox

Debemos utilizar la función add_meta_box() dentro de nuestro functions.php:

add_meta_box( $id, $title, $callback, $screen, $context, $priority, $callback_args)
  • id usado como el 'id' del formulario. No importa lo que escribas aquí, sólo recuerda que debe ser único
  • title título de la caja metabox
  • callback es una función la cuál debería imprimir el formulario
  • screen texto o array sobre dónde mostrar el metabox, en este caso nuestro post type
  • side lugar donde mostrar la caja en la edición del post ('normal', 'side' or 'advanced')
  • priority contexto en el que los metaboxes deberían mostrarse ('high', 'low', 'default')
  • callback_args son datos enviados como segundo parámetro a la función callback (no lo necesitamos en este ejemplo)

No es necesario crear una acción, pero lo recomiendo para centralizar y además podrías tener que añadir varios metaboxes en distintos tipos de post.

add_action( 'add_meta_boxes', 'all_post_metaboxes' );  
function all_post_metaboxes()
{  
    add_meta_box( 'book-additional-data', __('Book Data', 'child-theme'), 'book_data_meta_box', 'book', 'normal', 'high' );
}

function book_data_meta_box( $post ) {
    $values = get_post_meta( $post->ID, null, true );
    $author = esc_attr( get_post_meta( $post->ID, 'book_author', true ) );
    $featured = esc_attr( get_post_meta( $post->ID, 'book_featured', true ) );

    wp_nonce_field( 'book_additional_data_nonce', 'book_additional_data_nonce' );
    ?>
    <p>
        <label for="book_author">Author</label>
        <input type="text" name="book_author" id="book_author" value="<?php echo $author; ?>"/>
    </p>
    <p>
        <input type="checkbox" id="book_featured" name="book_featured" <?php checked( $featured, 'on' ); ?> />
        <label for="book_featured">Featured</label>
    </p>
    <?php
}

Book Metabox

Guardando el Metabox

Ahora que ya tenemos preparado nuestro formulario, es el momento de guardar los datos.

add_action( 'save_post', 'book_meta_box_save' );
function book_meta_box_save( $post_id )
{  
    // Bail if we're doing an auto save  
    if( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;

    // if our nonce isn't there, or we can't verify it, bail
    if( !isset( $_POST['book_additional_data_nonce'] ) || !wp_verify_nonce( $_POST['book_additional_data_nonce'], 'book_additional_data_nonce' ) ) return;

    // if current user can't edit this post, bail  
    if( !current_user_can( 'edit_post' ) ) return;

    // Make sure your data is set before trying to save it  
    if( isset( $_POST['book_author'] ) )
        update_post_meta( $post_id, 'book_author', wp_kses($_POST['book_author'], $allowed ) );

    // This is purely my personal preference for saving check-boxes
    $featured = isset( $_POST['book_featured'] ) && $_POST['book_featured'] ? 'on' : 'off';
    update_post_meta( $post_id, 'book_featured', $featured );
}

Esta función debe comprobar que el nonce es correcto por razones de seguridad y debemos asegurarnos que el usuario actual puede editar posts. Una vez que las comprobaciones son correctas, guardamos los datos utilizando update_post_meta().

¡Y eso es todo! Puedes jugar con tus conocimientos para crear nuevos campos como textarea, select, radio o incluso campos ocultos.

Recuerda limpiar los datos subidos por el usuario para evitar inyecciones de código... Incluso cuando sólo tu vas a usar el sitio.

Deja un comentario si esto fue útil