Crear Tipos Personalizados en WordPress

WordPress es más que un blog. Es un potente CMS muy versátil. Prueba de ello es que su contenido no se estructura únicamente en entradas o páginas. También podemos insertar contenido propio, con nuestra propia estructura y los campos que necesitemos. Nos estamos refiriendo a los Tipos Personalizados en WordPress (también conocidos como Custom Types).

Entendiendo los tipos personalizados

Sabemos que una entrada es una forma de insertar contenido en WordPress. Pulsamos en Entradas, Añadir nueva, y vemos los distintos campos (el título, el contenido, las categorías, etc). Una página es muy parecida a una entrada, pero a la vez se comporta diferente, y el formulario de inserción de contenido también es distinto del de las entradas. Un tipo personalizado no es ni una entrada, ni una página, es una forma de insertar contenido que nosotros definimos, tanto en campos como en estructura.

Para los que estéis familiarizados con el mundo de la programación orientada a objetos, podríamos decir que un Tipo Personalizado es eso, un objeto nuevo en WordPress, si entendemos las entradas y las páginas como objetos también. Si estuvieramos hablando en PHP, C#, o cualquier otro lenguaje orientado a objetos, Entradas y Páginas serían clases u objetos ya definidos por el lenguaje, como un int o un string, y un Tipo Personalizado también sería una clase, pero la definimos nosotros.

Por poner un ejemplo práctico, ¿has probado nuestro plugin de Diccionario de Términos y Definiciones? Este plugin inserta un nuevo campo en el menú (Definiciones), que funciona de forma parecida a una entrada, pero sin embargo, no es una entrada ni una página. Es un nuevo tipo personalizado en WordPress que nos permite añadir contenidos del tipo “definiciones”. Este tipo lo confeccionamos nosotros a la hora de hacer el plugin.

Existen formas sencillas de crear tipos personalizados, a través de plugins como Types. Sin embargo, hoy aprenderemos a definirlos desde código, sin necesidad de plugins externos.

Definir el tipo personalizado

La forma más fácil de hacer esto es, sin duda alguna, un plugin. Ya hemos explicado anteriormente las ventajas de usar un plugin: se puede activar y desactivar, no está ligado a un Theme específico, y no modifica el core de WordPress. Asi que manos a la obra, empezando por la cabecera del plugin:

<?php
/*
 * Plugin Name: Mi nuevo tipo personalizado
 * Description: Añade un nuevo tipo personalizado a WordPress
 * Author: Codigonexo
 * Author URI: https://www.codigonexo.com/
 * Version: 1.0
 */

Nuestro plugin añadirá el tipo personalizado cuando se inicie el plugin. Para ello, agregamos la siguiente acción:

add_action('init','crear_mi_tipo');

Cuando entre en juego el plugin, se activará la función ‘crear_mi_tipo’, que pasamos a definir a continuación:

function crear_mi_tipo(){
    register_post_type(
        'mi_tipo',
        array(
            'labels'=>array(
                'name'=>'Tipos',
                'singular_name'=>'Tipo',
                'add_new'=>'Añadir Nuevo',
                'add_new_item'=>'Añadir Nuevo Tipo',
                'edit_item'=>'Editar Tipo',
                'new_item'=>'Nuevo Tipo',
                'view_item'=>'Ver Tipo',
                'search_items'=>'Buscar Tipos',
                'not_found'=>'No se encontraron Tipos',
                'not_found_in_trash'=>'No se encontraron Tipos en la papelera'
            ),
        'public'=>true,
        'has_archive'=>true,
        'menu_position'=>20,        // Después de "Páginas", por ejemplo
        'menu_icon'=>plugins_url('/img/icons-16.png',__FILE__),
        'hierarchical'=>true,
        'supports'=>array(
                'title',
                'slug'
            )
        )
    );
}

La función ‘register_post_type‘ es la encargada de hacerlo. En primer lugar establecemos el nombre del tipo, el slug. En nuestro caso es ‘mi_tipo’. Este slug nos servirá más tarde para reconocer los contenidos de nuestro nuevo tipo.

Seguidamente, en un array establecemos las ‘labels’, que no son más que el nombre, el nombre en singular, en nombre en plural, y las cadenas de los diferentes botones de WordPress (Añadir Nuevo, etc). ¿Por qué tenemos que definir esto? Porque hay palabras en inglés, como “New”, que no varían con el género de las palabras en español, por lo que en algún momento encontraríamos problemas gramaticales.

Luego tenemos una serie de atributos que podemos establecer o no establecer. Podeis leerlas aquí, nosotros vamos a comentar las más importantes:

  • supports: Es un nuevo array muy interesante, ya que nos permite decirle al tipo qué campos, de los que WordPress ya implementa, va a utilizar. Por ejemplo, ‘title’ y ‘editor’ harán que sólo se vean los campos “Título” y el editor de contenidos normal de WordPress, nada más. Echad un ojo al codex para ver el resto de posibilidades.
  • hierarchical: Permite anidar contenidos.
  • menu_icon: Icono que tendrá nuestro tipo en el menú.
  • menu_position: la posición en el menú. Este valor numérico representa dónde va a aparecer el nuevo menú.
  • capability_type y capabilities: A ciertos usuarios les podemos permitir, o no, crear, editar y eliminar nuestros contenidos. Esto, en el resto de tipos, se controla mediante roles y permisos. Los permisos para las entradas son edit_post, delete_post, etc. Para nuestro Tipo Personalizado en WordPress, podemos establecer nuestros propios permisos. Con capability_type establecemos el string del tipo, y en capabilities establecemos los permisos, algo como esto: // Capabilities

Asi pues, ya hemos definido nuestro tipo. Ahora podemos guardar el archivo y activar el plugin, incluso insertar contenido. Técnicamente, ya es funcional.

¿Hay más tipos además de Entradas y Páginas?

Entradas y Páginas no son los únicos tipos que existen en WordPress. Existen ciertos tipos ya definidos por WordPress que no podemos utilizar a la hora de crear un nuevo tipo:

  • post (Entrada)
  • page (Página)
  • attachment (Adjuntos)
  • revision (Revisiones)
  • nav_menu_item (Item de Menu)

Debemos evitar usar estas palabras como primer parámetro de la función register_post_type.

Más campos a nuestro tipo personalizado

No siempre nos bastará con el título y el editor. Quizá hasta nos sobre el editor, y solo queramos establecer nuestros propios campos. Esto no es nada complicado de hacer si aprendemos a definir Meta Boxes, y dentro de ellas, agregamos contenido en HTML. Salvar los datos es otro cantar del que ahora hablaremos.

¿Qué es un meta box? Es un div, una caja, que aparecerá en el formulario de inserción de contenido de nuestro nuevo tipo personalizado. ¿Qué tiene dentro? Aquello que tu imaginación sea capaz de escribir en HTML.

En primer lugar, añadimos nuestra futura función de creación de meta boxes al momento en que WordPress carga las meta boxes.

add_action('add_meta_boxes','create_meta_boxes');

Y ahora, con una función simple, creamos las metaboxes:

function crear_meta_boxes(){
    add_meta_box('mi_meta_box','Meta Box de Prueba','mb1_content_callback','mi_tipo');
}

Hemos definido solo una, igual que podríamos haber definido cien. Cada add_meta_box necesita cuatro parámetros como mínimo: un slug, un título, la función a la que llamará para rellenar la caja, y un tipo de post en el que aparecerá. Ahora nos falta crear el relleno. Voy a simplificarlo mucho y a crear solo dos campos de texto.

function mb1_content_callback(){
    ?>
        Campo 1 <input type='text' name='field1' id='field1'>
        <br>
        Campo 2 <input type='text' name='field2' id='field2'>
    <?php
}

Ahora volvamos a mirar nuestro tipo personalizado (Añadir nuevo). Ha aparecido una caja con dos campos de texto. Es genial.

Bueno, sería genial si esos campos realmente se guardaran y sirviesen para algo. Lo habéis adivinado, si ahora pulsamos en publicar, esos campos no se guardan. Pero vamos a solucionar eso ya mismo.

Estructura de la base de datos de WordPress

Si ya sabes cómo funciona una base de datos de WordPress, puedes saltar al siguiente punto. Aunque suelo ser más práctico en mis explicaciones, necesito detenerme un segundo a explicar cómo funciona esta parte de WordPress en relación a la base de datos.

Cuando pulsamos en el botón “Publicar” de una entrada o página (o tipo personalizado), el contenido principal, como son el título, el contenido, la fecha, el tipo de entrada, el autor, etc. se guarda en la tabla “wp_posts”. El contenido secundario se guarda en la tabla “wp_postmeta”. Esto ocurre de forma automática.

No nos conviene en absoluto modificar el funcionamiento de la tabla wp_posts. Sin embargo, la tabla wp_postmeta es anárquica en este aspecto: solo sirve para guardar información correspondiente a un determinado post, que se reconoce por la id del post. La tabla wp_postmeta solo tiene cuatro campos en cada fila: id (identificador de fila), post_id (identificador de post, esto es muy necesario para relacionar un post con su contenido secundario), meta_key (el nombre del campo meta) y meta_value (el valor del campo meta).

Así, si al post cuya id es 15 le asignamos un campo “precio” con valor “20”, esta información se puede guardar sin problemas en la tabla wp_postmeta de esta manera:

  • id: Autoincremental dentro de la tabla wp_postmeta, no debemos establecer nada aquí.
  • post_id: 15
  • meta_key: precio
  • meta_value: 20

La tabla wp_postmeta está para eso, para guardar información secundaria, externa al funcionamiento de WordPress. Otra ventaja de usarla es que no necesitamos ejecutar sentencias SQL: para guardar los datos utilizamos update_post_meta, y para recuperarlo, get_post_meta.

Guardando el contenido personalizado

Como ya sabemos que podemos guardar la información que queramos en la tabla wp_postmeta, ahora debemos controlar qué ocurre cuando se guarda o actualiza un post. Para eso tenemos el hook (gancho) save_post, al que vamos a “enganchar” nuestra función de guardado.

add_action('save_post','save_mi_tipo',10,2);
function save_mi_tipo($tipo_id,$tipo){
    if($tipo->post_type == 'mi_tipo'){
        if(isset($_POST['field1'])){
            update_post_meta($tipo_id,'mi_tipo_field1',$_POST['field1']);
        }
        if(isset($_POST['field2'])){
            update_post_meta($tipo_id,'mi_tipo_field2',$_POST['field2']);
        }
    }
}

Lo primero que hacemos dentro de nuestra función es comprobar que estamos trabajando con el tipo correcto, el nuestro. No hay que olvidar que esta función se va a ejecutar siempre que se pulse el botón Publicar o Actualizar, sin distinción de tipos, así que debemos controlar que estemos en el tipo correcto (en este caso, mi_tipo). Tras ello, comprobamos que están entrando por $_POST dos valores, ‘field_1’ y ‘field_2’, y los guardamos con la función update_post_meta. De esta forma nos aseguramos que la información se guarda correctamente en la tabla wp_postmeta.

Estupendo, pero no funciona. ¿Por qué cuando guardamos y recargamos la página no vemos los campos rellenos con nuestro contenido? Porque tenemos que modificar ligeramente nuestro HTML, y rellenar los campos en el caso de existir contenido.

function mb1_content_callback(){
    ?>
        Campo 1 <input type='text' name='field1' id='field1' value='<?= (get_post_meta($_GET['post'],'field1') ? get_post_meta($_GET['post'],'field1') : "")?>'>
        <br>
        Campo 2 <input type='text' name='field2' id='field2' value='<?= (get_post_meta($_GET['post'],'field2') ? get_post_meta($_GET['post'],'field2') : "")?>'>
    <?php
}

¿Hemos terminado?

Como véis, los tipos personalizados en WordPress aportan a nuestro sistema nuevas formas de guardar contenido. Pero no hemos hablado de representar el contenido. A la hora de mostrar el contenido en el front-end, necesitaremos templates y plantillas nuevas en nuestros themes, que admitan correctamente nuestro nuevo tipo. Hablaremos de ello próximamente.

Si tenéis cualquier duda, justo debajo tenéis el formulario de comentarios. ¡También podéis contactar por nosotros via Facebook!

“Sin requerimientos o diseño, programar es
el arte de añadir bugs a un archivo de texto vacío”
– Louis Srygley

¿Te ha gustado el artículo?
Sé el primero en calificar esta publicación.
1 Star2 Stars3 Stars4 Stars5 Stars
Loading...
Artículo escrito por

¡Exprésate! Dejanos tu comentario

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

6 Comentarios

Marco

Hola, aun no entiendo como usar el código, creo un nuevo archivo php? o lo pego en el functions del theme.   Saludos y disculpen soy muy novato.

agux

Hola!! Estoy probando el plug-in y me temo que hay un pequeño (y típico) error:

add_action('add_meta_boxes','create_meta_boxes');
Tenemos create_meta_boxes. Ahora bien, a la hora de definir esa función/método:
function crear_meta_boxes()
Vemos que estamos utilizando crear_meta_boxes. Por eso, en un momento determinado, nos está fallando. Como digo: un típico error que solemos tener al pensar en dos idiomas a la hora de programar.

David

Veo que no salio completa aca lo pego parcialmente lo del campo1 Campo 1 < input type='text' name='field1' id='field1' value='ID,'mi_tipo_field1',true) ? get_post_meta(post->ID,'mi_tipo_field1',true) : "")?>'> Seria igual con el otro campo por si a alguien le sirve nuevamente gracias.

David

Muy buen post me ayudo mucho gracias la funcion callbak para recuperar los datos la tube que actualizar con esta function mb1_content_callback(){ global $post; ?> Campo 1 <input type='text' name='field1' id='field1' value='ID,'mi_tipo_field1',true) ? get_post_meta($post->ID,'mi_tipo_field1',true) : "")?>'> Campo 2 <input type='text' name='field2' id='field2' value='ID,'mi_tipo_field2',true) ? get_post_meta($post->ID,'mi_tipo_field2',true) : "")?>'>

Yllelder

El código: value='<?= (get_post_meta($_GET['post'],'field1') ? get_post_meta($_GET['post'],'field1') : "")?>'> que se supone que rellena el campo con el valor actual que hay en la tabla, no funciona. Con ese código el campo se rellena del código en sí, escrito tal cual, como que le falta alguna etiqueta de cierre o algo... y no doy con ella :(

Juan Pablo

Hola, y donde agrego los codigo solo en el archivo functions.php?