Custom Post Types (CPTs)
Aprende a expandir los tipos de contenido por defecto creando y gestionando Custom Post Types y taxonomías personalizadas para organizar estructuras de datos complejas ágilmente.
WordPress nació como plataforma de blogging, pero su verdadera potencia como CMS reside en su asombrosa flexibilidad. En este capítulo dejaremos atrás la limitación de usar exclusivamente "entradas" o "páginas". Aprenderás a diseñar arquitecturas de información a medida mediante el registro avanzado de Custom Post Types (CPTs) y taxonomías personalizadas. Exploraremos cómo configurar la interfaz de administración, asegurar una correcta internacionalización semántica y dominar la relación entre entidades para ejecutar consultas combinadas eficientes. Es el momento de estructurar tus datos de forma profesional y sin restricciones.
3.1 Registro avanzado de CPTs
En el núcleo de WordPress, un Custom Post Type (CPT) no es una estructura de base de datos separada; es simplemente una fila en la tabla wp_posts donde la columna post_type adquiere un valor definido por el desarrollador en lugar de los predeterminados (post, page, attachment, etc.). El "registro" de un CPT es, por tanto, el acto de instruir a la API de WordPress sobre cómo debe interactuar, enrutar, mostrar y gestionar este identificador específico.
La función central para esta tarea es register_post_type( $post_type, $args ). Sin embargo, para un desarrollo profesional, la configuración del array $args va mucho más allá de hacerlo visible en el panel de administración.
El Hook adecuado: init
El registro de un CPT siempre debe engancharse a la acción init. Engancharlo antes (como en plugins_loaded) puede causar que la funcionalidad de reescritura de URLs falle, y engancharlo después (como en wp_loaded) significa que el CPT no estará disponible cuando otros plugins o el propio núcleo intenten consultarlo.
PHP
Diseccionando el array $args (Configuración Avanzada)
Para tener un control absoluto sobre el comportamiento del CPT, es fundamental comprender la cascada de herencias que generan ciertos argumentos booleanos y cómo afectan al ecosistema de WP.
1. Visibilidad y Accesibilidad
El argumento public es un atajo. Si lo defines como true, WordPress establecerá automáticamente a true los siguientes argumentos (a menos que los sobrescribas explícitamente):
exclude_from_search: Falso (aparecerá en los resultados de búsqueda).publicly_queryable: Verdadero (se podrá acceder vía URL).show_in_nav_menus: Verdadero.show_ui: Verdadero.
En arquitecturas avanzadas, es común tener CPTs de uso interno (por ejemplo, para almacenar registros de logs o configuraciones complejas). Para un CPT "invisible" pero gestionable desde código:
PHP
2. Soporte del Editor Moderno (Gutenberg)
El argumento show_in_rest introdujo un cambio de paradigma. Originalmente concebido para exponer el CPT en la REST API (que veremos en el Capítulo 13), en las versiones actuales de WordPress es el interruptor maestro del editor de bloques.
Si show_in_rest es false (su valor por defecto) o se omite, el CPT utilizará el editor clásico (TinyMCE). Si se establece en true, WordPress cargará Gutenberg. Además, puedes modificar la ruta base de la API usando rest_base y rest_controller_class si necesitas personalizar la lógica de los endpoints.
3. Motor de Reescritura (Rewrite Rules)
El array rewrite controla cómo la WP_Rewrite API procesa las URLs del CPT.
slug: Por defecto usa el nombre del CPT, pero permite definir una URL amigable (ej. demiplugin_libroalibros).with_front: Si tu estructura de enlaces permanentes general tiene una base (como/blog/%postname%/), poner esto entruehará que tu CPT sea/blog/libros/mi-libro/. Ponerlo enfalsefuerza/libros/mi-libro/, lo cual es preferible en el 90% de los casos.pages: Soporte para paginación dentro del CPT.
Importante: Cambiar el slug requiere limpiar las reglas de reescritura. No uses flush_rewrite_rules() dentro del hook init (destruirá el rendimiento). Debes hacerlo únicamente en la rutina de activación del plugin (Capítulo 2.3).
4. Array de Capacidades (supports)
Define qué metaboxes y características del núcleo se cargan en la pantalla de edición.
TEXT
Si omites el argumento supports, WordPress asignará ['title', 'editor'] por defecto. Si pasas false, el CPT no tendrá soporte para ninguna de estas características nativas, lo cual es útil si planeas construir una interfaz de edición 100% personalizada basada únicamente en metaboxes propios (Capítulo 4).
3.2 Etiquetas y argumentos de interfaz
Cuando se registra un Custom Post Type, la experiencia del usuario (UX) dentro del panel de administración de WordPress depende por completo de la configuración semántica de sus etiquetas y de los argumentos que definen su comportamiento visual. Un CPT con etiquetas mal configuradas mostrará textos genéricos heredados del tipo de contenido post, lo que restará profesionalidad al plugin y confundirá al administrador.
Internacionalización semántica: El uso de _x()
Para construir el array de etiquetas (labels), no basta con utilizar la función de traducción estándar __(). En muchos idiomas, incluidos el español y otras lenguas romances, la flexión de género afecta tanto a los sustantivos como a los adjetivos y verbos asociados.
Por ejemplo, la cadena "Add New" se traduce como "Añadir nuevo" si el CPT es un "Libro", pero debe ser "Añadir nueva" si el CPT es una "Factura". Para resolver esto sin hardcodear el idioma, WordPress proporciona la función _x(), la cual permite añadir un contexto sintáctico para los traductores.
PHP
Ubicación de las etiquetas en la interfaz del Administrador
El siguiente esquema en texto plano ilustra cómo se mapean las principales etiquetas configuradas dentro del ciclo de vida visual del panel de control de WordPress:
TEXT
Argumentos de control de la UI
Más allá de los textos, existen argumentos específicos dentro del array de $args en register_post_type() que determinan la accesibilidad y el posicionamiento del CPT dentro del entorno gráfico.
menu_position (Ubicación en el menú lateral)
Este argumento acepta un número entero que determina la prioridad de aparición en la barra lateral. Si se omite, WordPress lo colocará por defecto debajo de los Comentarios (posición 25).
Conocer las posiciones exactas del núcleo es crucial para evitar colisiones visuales:
5: Debajo de Entradas (Posts).10: Debajo de Medios (Media).15: Debajo de Enlaces (Links).20: Debajo de Páginas (Pages).25: Debajo de Comentarios.60: Debajo del primer separador de menú.65: Debajo de Plugins.70: Debajo de Usuarios.75: Debajo de Herramientas.80: Debajo de Ajustes.100: Debajo del segundo separador de menú.
menu_icon (Identidad visual)
Para definir el icono del menú lateral, existen dos vías profesionales:
- Dashicons: La biblioteca nativa de fuentes de iconos de WordPress. Se pasa el nombre de la clase directamente (ej.
'dashicons-book-alt'). - SVG Vectorial Embebido: Para personalización de marca avanzada, se puede pasar un string con un SVG codificado en Base64. Esto evita peticiones HTTP adicionales y asegura consistencia independientemente del tema de administración del usuario.
PHP
show_in_menu (Anidación de CPTs)
Este parámetro acepta un valor booleano o un string. Al pasar un string con la ruta de un archivo .php de la administración, puedes agrupar tu CPT dentro de un menú existente en lugar de crear un elemento de primer nivel.
- Anidar dentro de Entradas:
'show_in_menu' => 'edit.php' - Anidar dentro de Ajustes:
'show_in_menu' => 'options-general.php' - Anidar dentro de un menú personalizado propio creado por el plugin:
'show_in_menu' => 'mi_panel_de_control_slug'
Modificación del marcador de posición del título
Por defecto, la caja de texto donde se introduce el título del CPT muestra el texto genérico "Añadir el título". Modificar este comportamiento no se realiza mediante un argumento directo en register_post_type(), sino interceptando el filtro enter_title_here.
A continuación, se muestra cómo integrar de forma limpia esta lógica dentro de la estructura orientada a objetos del desarrollo del CPT:
PHP
3.3 Registro de taxonomías propias
Así como los Custom Post Types extienden los tipos de contenido en WordPress, las taxonomías personalizadas permiten estructurar las relaciones y la categorización de dichos contenidos de forma multidimensional. En el núcleo de WordPress, una taxonomía es un sistema de clasificación (como las categorías o etiquetas nativas) cuyos términos se almacenan en la tabla wp_terms y se vinculan a los contenidos mediante wp_term_relationships.
La función del núcleo designada para este propósito es register_taxonomy( $taxonomy, $object_type, $args ). Al igual que con los CPTs, un registro avanzado requiere un control preciso de sus argumentos y su ejecución en el momento adecuado del ciclo de vida de WordPress.
El Hook adecuado y el orden de ejecución
Las taxonomías personalizadas deben registrarse siempre dentro del hook init. Es técnicamente posible y recomendado registrar tanto el CPT como su taxonomía asociada dentro de la misma función callback conectada a init para mantener el código cohesionado.
PHP
Jerárquicas vs. No Jerárquicas: El argumento hierarchical
El argumento hierarchical determina el comportamiento estructural y la interfaz de usuario de la taxonomía dentro del panel de administración:
'hierarchical' => true(Estilo Categorías): Permite relaciones de tipo padre-hijo entre los términos. En el editor de contenidos (Gutenberg o Clásico), se renderiza como una lista de casillas de verificación (checkboxes). Los usuarios eligen términos preexistentes y pueden crear nuevos directamente sin salir de la pantalla de edición.'hierarchical' => false(Estilo Etiquetas/Tags): No permite herencia ni elementos padre. En la interfaz se muestra como una caja de texto donde los términos se introducen separados por comas y cuenta con un autocompletado basado en los términos más utilizados.
Argumentos avanzados de control
Para afinar la integración de la taxonomía en el ecosistema del sitio, se deben dominar los siguientes parámetros específicos:
show_admin_column
Establecer este argumento en true instruye a WordPress para que cree automáticamente una columna personalizada en la tabla de listado del CPT asignado (en este caso, en la pantalla de edit.php?post_type=miplugin_libro). Esto ahorra al desarrollador la necesidad de interceptar manualmente los filtros de columnas del admin para mostrar los términos asignados a cada entrada.
meta_box_cb
Permite cambiar por completo la función callback encargada de renderizar la interfaz de la taxonomía en la pantalla de edición del post. Si se pasa false, se remueve por completo el metabox nativo de la barra lateral. Esto es una práctica común cuando el plugin implementa una interfaz de selección personalizada mediante JavaScript o controles avanzados en metaboxes propios.
rewrite (Reglas de enrutamiento)
Al igual que con los CPTs, controla la estructura de los enlaces permanentes de las páginas de archivo de la taxonomía.
slug: Define la base de la URL (ej.midominio.com/genero/ciencia-ficcion/).hierarchical: Si se establece entrue, la URL reflejará la estructura interna de los términos (ej.midominio.com/genero/novela/ciencia-ficcion/).
El peligro de register_taxonomy_for_object_type()
Existe una función en el núcleo llamada register_taxonomy_for_object_type(). Su uso es un error común cuando se registran taxonomías propias para CPTs propios. Esta función está diseñada exclusivamente para vincular una taxonomía existente (como las categorías nativas category) a un tipo de contenido.
Para taxonomías creadas por tu propio plugin, la vinculación debe declararse directamente pasando el identificador del CPT en el segundo parámetro (el array $object_type) de la función register_taxonomy(), tal como se ejemplificó en el código de la sección anterior ([ self::POST_TYPE ]).
Estructura de almacenamiento en Base de Datos
El siguiente diagrama en texto plano muestra cómo interactúan las tablas nativas de WordPress cuando se registra y asigna un término de una taxonomía personalizada:
TEXT
3.4 Relación entre CPTs y taxonomías
El verdadero poder de las arquitecturas de datos en WordPress se revela cuando los Custom Post Types y las taxonomías trabajan en conjunto. Mientras que el CPT define el "qué" (el objeto de contenido), la taxonomía define el "cómo se agrupa". Esta relación de muchos a muchos permite construir consultas complejas y estructurar la navegación del sitio.
Consultas combinadas con WP_Query y tax_query
Para extraer contenidos de un CPT basándose en los términos de una taxonomía personalizada, la clase WP_Query proporciona el argumento tax_query. Este parámetro requiere un array multidimensional, lo que permite realizar cruces lógicos complejos (AND, OR) entre múltiples taxonomías si fuera necesario.
A continuación, se muestra cómo recuperar los últimos 10 libros que pertenecen al género "Ciencia Ficción":
PHP
Recuperación de términos desde un CPT
Cuando te encuentras dentro del loop o tienes el ID de un post específico, frecuentemente necesitas mostrar a qué términos está asociado. Para taxonomías personalizadas, funciones como the_category() no sirven. Debes utilizar get_the_terms().
PHP
Integración avanzada en el panel de administración
Si definiste 'show_admin_column' => true al registrar la taxonomía, WordPress mostrará los términos en la tabla listado del CPT. Sin embargo, para sitios con gran volumen de datos, los administradores necesitarán filtrar los CPTs mediante un menú desplegable por taxonomía.
WordPress no crea este filtro desplegable automáticamente para taxonomías personalizadas. Debes construirlo enganchándote a la acción restrict_manage_posts.
PHP
El núcleo de WordPress interceptará automáticamente el parámetro GET generado por este formulario y modificará la consulta principal (WP_Query) de la tabla de administración, filtrando los resultados sin necesidad de código adicional de nuestra parte.
Resumen del capítulo
En este capítulo, hemos abordado la creación y estructuración de modelos de datos mediante las APIs de WordPress. Hemos visto que el registro de Custom Post Types (register_post_type) y taxonomías (register_taxonomy) debe ejecutarse de forma segura en el hook init, prestando especial atención a los argumentos que controlan la visibilidad, el soporte de características como Gutenberg (show_in_rest) y las reglas de reescritura de URLs.
Analizamos la importancia de la internacionalización semántica (_x()) para construir interfaces de administración profesionales. Finalmente, exploramos cómo relacionar ambas entidades, ejecutando consultas condicionales complejas con WP_Query y mejorando la experiencia de gestión en el panel de administración mediante filtros personalizados. Esta base estructural es esencial antes de pasar a la inyección de datos granulares a nivel de campo.
© 2026 Esdocu. Contenido bajo licencia MIT.
Editar esta página