A veces, una instalación de WordPress por defecto se puede quedar pequeña para según qué proyecto, por lo que necesitamos vitaminarlo para conseguir llevar a cabo los requisitos del mismo.

Aunque bien es cierto que jugando con las plantillas y categorías podríamos conseguir efectos similares, no es lo óptimo de cara a una buena arquitectura de la información. Cuanto más organicemos nuestro contenido más fácil será saber qué es cada cosa y cómo funciona el sitio web.

¿Qué son los custom post types?

Los Custom Post Types son tipos de entrada personalizados que puedes agregar a tu WordPress. Por ejemplo, WordPress por defecto trae como tipo de entrada:

  • Entradas
  • Páginas
  • Adjuntos
  • Revisión
  • Menú de navegación

Como ejemplo, en uno de los proyectos personales en el que estoy trabajando actualmente (aunque ya lo había hecho en otras ocasiones), he creado un custom post type para mostrar fichas de productos, dejando el blog intacto para poder informar al visitante sobre las novedades del mercado de dichos productos.

Hay miles de tutoriales sobre Custom Post Types y un hermoso Codex que tiene toda la información al respecto, pero no es fácil si no sabes cómo encararlo. Yo voy a tratar de enseñarte la que, para mí, es la forma correcta de hacerlo.

Usando Etiquetas (Labels) para los tipos de entrada

custom post type sin etiquetas
Utilizar etiquetas para los custom post types y las taxonomías es muy importante por el simple hecho de que ayuda a diferenciar los custom post types de otras herramientas que trae WordPress por defecto. Cuando añades una nueva entrada, página, categoría o etiqueta, en la parte superior de la página dice algo como “Añadir nuevo _Algo_”, dependiendo de qué estés añadiendo.

Si no utilizas etiquetas para cambiar esta parte y saber qué estas editando, automáticamente pondrá por defecto “Entrada” para los tipos de entrada y “Categoría” o “Etiqueta” para las taxonomías ya sean jerárquicas o no, respectivamente (como se ve en la imagen superior).

Configurando las etiquetas para mostrar el Custom Post Type

Ya te he mencionado que en el Codex hay información más que suficiente para hacer todo esto, pero aquí va un ejemplo rápido con su explicación, todo este código irá en el functions.php de nuestro tema:

// La función no será utilizada antes del 'init'.
add_action( 'init', 'my_custom_init' );
/* Here's how to create your customized labels */
function my_custom_init() {
	$labels = array(
	'name' => _x( 'Libros', 'post type general name' ),
        'singular_name' => _x( 'Libro', 'post type singular name' ),
        'add_new' => _x( 'Añadir nuevo', 'book' ),
        'add_new_item' => __( 'Añadir nuevo Libro' ),
        'edit_item' => __( 'Editar Libro' ),
        'new_item' => __( 'Nuevo Libro' ),
        'view_item' => __( 'Ver Libro' ),
        'search_items' => __( 'Buscar Libros' ),
        'not_found' =>  __( 'No se han encontrado Libros' ),
        'not_found_in_trash' => __( 'No se han encontrado Libros en la papelera' ),
        'parent_item_colon' => ''
    );
 
    // Creamos un array para $args
    $args = array( 'labels' => $labels,
        'public' => true,
        'publicly_queryable' => true,
        'show_ui' => true,
        'query_var' => true,
        'rewrite' => true,
        'capability_type' => 'post',
        'hierarchical' => false,
        'menu_position' => null,
        'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments' )
    );
 
    register_post_type( 'libro', $args ); /* Registramos y a funcionar */
}

Evidentemente, es posible que aquí haya mucho más código que en otros tutoriales de Custom Post Types, pero así es como puedes hacer tus custom post types mucho más “custom”, aunque ya sean personalizados después de todo. Además, sólo te lleva un par de segundos hacer esto.

ejemplo custom post type con etiquetas

Espero que hayas captado la idea hasta ahora. Simplemente mira en la imagen lo bonito que queda ahora en la imagen de la derecha; para tí, para tus clientes u otros usuarios del sitio web que vayan a ver la personalización que has hecho. Cualquiera que colabore en tu web podrá manejarla de una forma muy sencilla. Mola, ¿verdad?

Algunas funciones para controlar los Custom Post Types

Lo siguiente es un listado de las funciones que nos facilita WordPress con las que podremos controlar nuestros Custom Post Types:

  • post_type_exists() – Revisa si existe un custom post type.
  • is_post_type_hierarchical( $post_type ) – Cuándo el tipo de post es jerárquico. Si retorna falso es que no lo es.
  • get_post_type( $post ) – Recupera el tipo de entrada del artículo en cuestión o un post específico.
  • get_post_type_object( $post_type ) –
    Recupera un objeto del tipo de entrada por nombre.
  • get_post_types( $post ) – Obtiene una lista de todos los tipos de entrada.
  • register_post_type() – Registra un nuevo tipo de entrada. No utilizar antes del init.
  • get_post_type_capabilities() – Crea un objeto con todos los permisos de los tipos de entrada personalizados.

Hay muchas más que podéis consultar en el Codex.

Otros añadidos que debes conocer para los Custom Post Types

Obviamente no iba a dejar esto así, a medio empezar. Si te fijas en la última imagen, la de las etiquetas del custom post type personalizadas, no tiene categorías ni etiquetas… Un gran fallo para según qué tipo de producto o contenido vayamos a tratar.

También está documentado en el codex, pero vamos a aplicarlo al ejemplo anterior:

// Lo enganchamos en la acción init y llamamos a la función create_book_taxonomies() cuando arranque
add_action( 'init', 'create_book_taxonomies', 0 );
 
// Creamos dos taxonomías, género y autor para el custom post type "libro"
function create_book_taxonomies() {
	// Añadimos nueva taxonomía y la hacemos jerárquica (como las categorías por defecto)
	$labels = array(
	'name' => _x( 'Géneros', 'taxonomy general name' ),
	'singular_name' => _x( 'Género', 'taxonomy singular name' ),
	'search_items' =>  __( 'Buscar por Género' ),
	'all_items' => __( 'Todos los Géneros' ),
	'parent_item' => __( 'Género padre' ),
	'parent_item_colon' => __( 'Género padre:' ),
	'edit_item' => __( 'Editar Género' ),
	'update_item' => __( 'Actualizar Género' ),
	'add_new_item' => __( 'Añadir nuevo Género' ),
	'new_item_name' => __( 'Nombre del nuevo Género' ),
);
register_taxonomy( 'genero', array( 'libro' ), array(
	'hierarchical' => true,
	'labels' => $labels, /* ADVERTENCIA: Aquí es donde se utiliza la variable $labels */
	'show_ui' => true,
	'query_var' => true,
	'rewrite' => array( 'slug' => 'genero' ),
));

Con esto ya tenemos la primera taxonomía, a continuación vamos con la segunda:

// Añado otra taxonomía, esta vez no es jerárquica, como las etiquetas.
$labels = array(
	'name' => _x( 'Escritores', 'taxonomy general name' ),
	'singular_name' => _x( 'Escritor', 'taxonomy singular name' ),
	'search_items' =>  __( 'Buscar Escritores' ),
	'popular_items' => __( 'Escritores populares' ),
	'all_items' => __( 'Todos los escritores' ),
	'parent_item' => null,
	'parent_item_colon' => null,
	'edit_item' => __( 'Editar Escritor' ),
	'update_item' => __( 'Actualizar Escritor' ),
	'add_new_item' => __( 'Añadir nuevo Escritor' ),
	'new_item_name' => __( 'Nombre del nuevo Escritor' ),
	'separate_items_with_commas' => __( 'Separar Escritores por comas' ),
	'add_or_remove_items' => __( 'Añadir o eliminar Escritores' ),
	'choose_from_most_used' => __( 'Escoger entre los Escritores más utilizados' )
);
 
register_taxonomy( 'escritor', 'libro', array(
	'hierarchical' => false,
	'labels' => $labels, /* ADVERTENCIA: Aquí es donde se utiliza la variable $labels */
	'show_ui' => true,
	'query_var' => true,
	'rewrite' => array( 'slug' => 'escritor' ),
));
} // Fin de la función create_book_taxonomies().

Deberías notar cómo es bastante similar crear las etiquetas para el custom post type y para las taxonomías. ¡Realmente el proceso es idéntico!

ejemplo custom post type taxonomia con etiquetas

Ahora se ve algo como en la imagen de la izquierda; mucho mejor, ¿verdad? Ya tenemos nuestro custom custom post type listo para ser utilizado. En este caso he puesto el ejemplo de libros porque es el que utilizan en el códex (para quien busca pistas: no, no estoy montando un proyecto de libros :-D).

Algunas funciones útiles para administrar las taxonomías

Al igual que con los custom post types, existen funciones que nos permiten manejar nuestras taxonomías (sean personalizadas o no):

  • get_taxonomies() – Obtienes una lista de las taxonomías registradas.
  • get_object_taxonomies($object_type) – Retorna todas las taxonomías que pertenecen al $object_type especificado.
  • get_taxonomy() – Recupera la taxonomia especificada.
  • taxonomy_exists() – Comprueba que la taxonomía existe. Falso si no existe.
  • is_taxonomy_hierarchical() – Nos dice si una taxonomía es jerárquica. Falso en caso negativo.
  • register_taxonomy – Crea o modifica un objeto de taxonomía. No usar antes del init.

No voy a enumerar todas, podéis verlas en el Codex, concretamente aquí.

Ahora no creo que tengas excusa para exprimir aún más tu instalación de WordPress y empezar a utilizarlo como un Framework de desarrollo.

Puedes contarme qué piensas, si te ha resultado útil y en qué utilizas tú los Custom Post Types o las dudas que tengas en los comentarios.

No olvides compartirlo si te ha gustado y darle difusión, eso me animará a seguir escribiendo y creando tutoriales como este.

59 comentarios en “Custom Post Types y Taxonomías en WordPress, la forma correcta

      1. Totalmente de acuerdo contigo amigo.
        A veces los plugins vienen con cientos de lineas de código y módulos solo para hacer algo tan sencillo que puede ser recursivo tal vez pero para el objetivo en especifico no es lo mas óptimo, si estamos en la posibilidad de desarrollarlo por que no hacerlo :)

  1. Hola buenos tutoriales de antemano,quiero crear un formulario para rellenar por los usuarios y que creen borradores a falta de aprobacion o no.. a mi Custom Post Types no consigo hacer esto,usted sabe alguna referencia a esto ? o algún tutorial de como conseguir hacer esto sin plugin.

    Gracias y Saludos

    1. Hola, para lo que comentas tienes que recoger los datos desde el formulario y utilizar la función wp_inser_post() http://codex.wordpress.org/Function_Reference/wp_insert_post

  2. Perdón si me pongo pesado esto hace entrada
    en los post
    ”,
    ‘post_author’ => $user->ID,
    ‘post_category’ => array($post_category),
    ‘post_content’ => $post_content,
    ‘post_title’ => $post_title,
    ‘post_status’ => ‘publish’
    );

    $post_id = wp_insert_post($new_post);

    // This will redirect you to the newly created post
    $post = get_post($post_id);
    wp_redirect($post->guid);
    }
    ?>

    NOMBRE

    CATEGORIA

    MENSAGE

    que debo de llamar para que lo haga en libros?

    Siento mi ignorancia

    1. Inserto codigo correcto

      '',
      'post_author' => $user->ID,
      'post_category' => array($post_category),
      'post_content' => $post_content,
      'post_title' => $post_title,
      'post_status' => 'publish'
      );

      $post_id = wp_insert_post($new_post);

      // This will redirect you to the newly created post
      $post = get_post($post_id);
      wp_redirect($post->guid);
      }
      ?>

      NOMBRE

      CATEGORIA

      MENSAGE

  3. Muchas gracias asi era…
    $new_post = array(
    ‘ID’ => ”,
    ‘post_author’ => $user->ID,
    ‘post_category’ => array($post_category),
    ‘post_content’ => $post_content,
    ‘post_title’ => $post_title,
    ‘post_status’ => ‘publish’,
    ‘post_type’ => ‘libro’

    nota el código no se ve bien en los comentarios.Seria interesante agregarlo en el post
    Gracias me fuiste de gran ayuda

  4. post_category’ => array($post_category),

    otra duda que no puedo solucionar cambie category por genero pero no ….
    que debo de llamar para seleccionar un genero…

  5. Hola, muchas gracias por el post y la manera de explicarlo. Me ha resultado muy sencillo.

    Lo único es que ha creado el tipo de dato Producto (encima de apariencia) y he creado un nuevo producto pero a la hora de querer ver previamente como quedaría, le he dado al botón “ver Producto” y la página me dice que no lo encuentra: “Page not found” pero está en la lista de Productos.
    He probado a buscarlo mediante el search por título de producto y lo encuentra, le doy a ver y vuelve a salir la página not found.

    ¿Hay que configurar algo más o es que no se puede mostrar como “post”?

    Muchas gracias

    Saludos,
    Zaida

    1. Hola Zaida, por defecto usa el single.php del theme para mostrar los custom post types, salvo que crees una plantilla diferente.

      Si la plantilla que utilizas está bien construida no habría problema.

  6. Muy buen contenido y bien explicado, yo no soy programadora sino diseñadora grafica… Asi que esto me queda grande, pero estoy empeñada en conseguir meter en el blog que tengo un directorio de “productos” con su ficha (no es para venta online), lo malo es la visualización, que aparezca un árbol a la derecha para saber donde estas me parece increible porque lo veo básico, pero no he encontrado nada que se parezca en WP,

    1. Hola Cristina, WordPress es una herramienta. Sabiendo utilizarla (o desarrollar con ella, en este caso) se puede hacer cualquier cosa.

      Te animo a que contrates a un profesional que te ayude con lo que quieres hacer o te asesore sobre la forma más fácil de lograrlo.

      Saludos.

  7. Hola Dario, lo primero agradecerte enormemente ttus entradas del Blog, me parecen muy interesante y además contagias tu entusiasmo en cada una de las entradas.
    Yo quería preguntarte como se podría personalizar el icono que sale en el menú del dashboard cuando creas un nuevo Custom Type, para poder sustituir a la “chincheta”.

    Un saludo

      1. Estupendo, estaba buscando algo así!! muchas gracias por tu ayuda!

        Acabo de descubrir contigo el tema de los “custom types” y estoy enormemente emocionado con la posibilidades que se les puede dar!

        Ha cambiado totalmente mi visión de WordPress!!

        Gracias de nuevo

      2. Dario, te escribo de nuevo para contarte que haciendo pruebashe visto que si, en tu código inicial, añades en el array de args
        ‘menu_icon’ => ”,
        y dentro de las ” pones el nombre del icono que corresponde dentro de los soportados (http://melchoyce.github.io/dashicons/)

        de tal manera, por ejemplo:

        $args = array( ‘labels’ => $labels,
        ‘public’ => true,
        ‘publicly_queryable’ => true,
        ‘show_ui’ => true,
        ‘query_var’ => true,
        ‘rewrite’ => true,
        ‘capability_type’ => ‘post’,
        ‘hierarchical’ => false,
        ‘menu_position’ => null,
        ‘menu_icon’ => ‘dashicons-megaphone’,
        ‘supports’ => array( ‘title’, ‘editor’, ‘author’, ‘thumbnail’, ‘excerpt’, ‘comments’ )
        );

        Funciona :)

        Un saludo

  8. Hola, faltaria añadir a este tutorial, la parte de custom labels.

    Imaginate que yo a mi libro le quiero indicar el año de edicion, el numero de paginas, una imagen de la portada, el peso… el tipo de tapa (dura o blanda)…

    Tienes algo ya hecho al respecto?

  9. Estupendo, me ha venido de perlas para introducirme en el mundo de los custom types.

    Estaría bien más tutoriales de este tipo, tan bien detallados.

    Muchas gracias a su autor

  10. Muy bueno el artículo, gracias por tomarte el tiempo y publicarlo.

    Una consulta que quizás abarca un poco más el tema:
    cuando defino más de una taxonomía para un CPT “Productos” al hacer el rewrite solo funciona con la última taxonomía que defino.
    Todas usan la misma función.
    ¿A qué puede deberse esto?

    Muchas gracias

    1. Hola, es posible que a la hora de hacer el registro de la taxonomía estés registrando el mismo identificador, por eso sólo ves la última.

  11. Hola Darío, hasta cuantos custom post type se pueden agregar? Yo ya voy 4 y uno 5to ya no aparece, de ser así, hay forma de poder agregar más? Alguna función?

  12. como cambias el orden de estas nuevas opciones en el panel de lugar?
    me aparecen debajo de comentarios, me gustaria q apareciera debajo de entradas?

  13. Hola Dario, buenos tutos, muy interesantes. Pero como todos los tutoriales que sigo sobre cutom post type, no funciona…
    Mi problema viene cuando añado la función para las taxonomias, no se si lo incluyo mal; lo pongo despues de: add_action ( ‘init’, ‘create_book_taxonomies’, 0); de la función anterior. Despues tengo otro poblema, me pasa igual que a Zaida, no sale en la plantilla, estoy usando, para esta pruebas, la plantilla twentyfifteen y la versión de WP es 4.3.1, ¿tendrá algo que ver?

    1. Hola Isra, te aseguro que funciona.

      La función del ejemplo, con las dos taxonomías, queda así:


      // Lo enganchamos en la acción init y llamamos a la función create_book_taxonomies() cuando arranque
      add_action( 'init', 'create_book_taxonomies', 0 );

      // Creamos dos taxonomías, género y autor para el custom post type "libro"
      function create_book_taxonomies() {
      // Añadimos nueva taxonomía y la hacemos jerárquica (como las categorías por defecto)
      $labels = array(
      'name' => _x( 'Géneros', 'taxonomy general name' ),
      'singular_name' => _x( 'Género', 'taxonomy singular name' ),
      'search_items' => __( 'Buscar por Género' ),
      'all_items' => __( 'Todos los Géneros' ),
      'parent_item' => __( 'Género padre' ),
      'parent_item_colon' => __( 'Género padre:' ),
      'edit_item' => __( 'Editar Género' ),
      'update_item' => __( 'Actualizar Género' ),
      'add_new_item' => __( 'Añadir nuevo Género' ),
      'new_item_name' => __( 'Nombre del nuevo Género' ),
      );
      register_taxonomy( 'genero', array( 'libro' ), array(
      'hierarchical' => true,
      'labels' => $labels, /* ADVERTENCIA: Aquí es donde se utiliza la variable $labels */
      'show_ui' => true,
      'query_var' => true,
      'rewrite' => array( 'slug' => 'genero' ),
      ));

      // Añado otra taxonomía, esta vez no es jerárquica, como las etiquetas.
      $labels = array(
      'name' => _x( 'Escritores', 'taxonomy general name' ),
      'singular_name' => _x( 'Escritor', 'taxonomy singular name' ),
      'search_items' => __( 'Buscar Escritores' ),
      'popular_items' => __( 'Escritores populares' ),
      'all_items' => __( 'Todos los escritores' ),
      'parent_item' => null,
      'parent_item_colon' => null,
      'edit_item' => __( 'Editar Escritor' ),
      'update_item' => __( 'Actualizar Escritor' ),
      'add_new_item' => __( 'Añadir nuevo Escritor' ),
      'new_item_name' => __( 'Nombre del nuevo Escritor' ),
      'separate_items_with_commas' => __( 'Separar Escritores por comas' ),
      'add_or_remove_items' => __( 'Añadir o eliminar Escritores' ),
      'choose_from_most_used' => __( 'Escoger entre los Escritores más utilizados' )
      );

      register_taxonomy( 'escritor', 'libro', array(
      'hierarchical' => false,
      'labels' => $labels, /* ADVERTENCIA: Aquí es donde se utiliza la variable $labels */
      'show_ui' => true,
      'query_var' => true,
      'rewrite' => array( 'slug' => 'escritor' ),
      ));
      } // Fin de la función create_book_taxonomies().

  14. Hola Darío:

    En primer lugar agradecerte este tutorial que es muy interesante.

    En segundo lugar, querría hacerte una pregunta que no encuentro respondida en ningún sitio y me confunde bastante.

    He creado un Custom Post Type (CPT) con el nombre “Testimonios” para mi sitio web (www. yogaocularmadrid.es/testimonios). Disculpa que meta la dirección web pues no tengo ánimo de spam; lo que sí me gustaría es que vieras el resultado de lo que quiero imitar en mi nuevo sitio hecho con Genesis Framework y la plantilla Foodie.

    Esta plantilla no incluye un cpt que pueda utilizar, y por esto lo estoy creando a mano.

    El caso es que he conseguido crearlo, le he añadido páginas, pero no sé como añadir la página del cpt al menú para que la gente, pulsando sobre él, pueda acceder a todos los testimonios un poco al estilo de una página de blog.

    También he creado las taxonomías y me gustaría que, al pulsar sobre una de ellas (como en la página actual), se seleccionasen únicamente las páginas que estén relacionadas en esa taxonomía.

    Por último decirte que todo esto lo he realizado a través de crear dos plugins: uno para el cpt y el otro para las taxonomías. Así no desaparecerán si cambio de tema.

    ¿Me podrías decir cómo puedo insertar la página general de cpt “Testimonios” en el menú principal del sitio para que sea accesible por los usuarios?.

    Muchas gracias y ¡buen trabajo!.

    Eduardo

    1. Hola Eduardo, los Custom Post Type siempre tienen la url como esta: http://misitio.com/nombrecustomposttype/, por lo que puedes añadir manualmente el enlace a dicho custom post type, o bien añadir la funcionalidad del custom post type al editor de menus.

      Para esto, tienes que habilitar la opción “show_in_nav_menus” a “true” dentro de los argumentos del custom post type.

  15. Hola! he usado tu código en muchos de los sitios en los que trabajo. Muchas gracias!
    Ahora quiero hacerte una consulta. Tengo 2 tipos de entradas personalizadas, y quisiera que una sea “hija” de la otra. No logro encontrar una ayuda clara para poder hacerlo. Te agradeceré mucho tu ayuda!!!

  16. Que seria de la vida sin personas como tu que nos ayudan a los menos ilustrados…
    Estoy tratando de crear dos Labels para dos tipos de custom post types que necesito definir en una plantilla personalizada, pero no logro entender como configurar el archivo donde se mostrará estos custom post y como deberia ir el loop en dichos ‘archivos.php’.
    Podrias por favor darme un ejemplo de como deberia hacerlo?
    Infinitas gracias Dario!

    1. Hola Oscar, perdona la tardanza en contestar.

      No entiendo muy bien tu cuestión; pero para mostrar los custom post types tienes plantillas específicas, como por ejemplo archive-{post_type}.php o single-{post_type}.php; por lo que sólo alterarás el front de ese custom post type.

      Saludos.

  17. como siempre muy interesante cada tema, eres como el traductor de el codex, de hecho un proyecto como ese te quedaria muy bien ya que eres la persona que explica mejor el codex de wordpress que he encontrado en internet, porque una cosa es tener el codex y otra cosa es llevarlo a la practica, gracias por tu valiosa ayuda…

    1. Hola Frank, gracias por tus comentarios. Actualmente no tengo cursos online preparados, pero quién sabe si en un futuro… jeje.

      Por ahora, puedes suscribirte a mi newsletter, donde recibirás todos los artículos en tu correo electrónico.

  18. Hola Darío,
    buscando info sobre Custom Pot Types me he encontrado con este post, pero lo escribiste hace 2 años… sigue siendo el mismo código desde entonces?
    Muchas gracias!!

  19. Hola Dario, en el ejemplo que comentas, si yo quisiera mostrar todos los libros de un genero concreto, por ejemplo “Ficción”, tendría que hacer una consulta personalizada o se sirve de alguna plantilla como archive-libros.php?

  20. Me funciona perfecto, el único problema que tengo es que cuando decido hacer unos botones con el nombre de la categoría, lo repite en cuanto post contenga, es decir que si la categoría tiene 5 post, 5 veces se repite el botón, sabes alguna solución al momento de llamar el array, como lo limito para que salga solo una vez. Saludos

Deja un comentario

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