Custom Posts
Usamos los campos customPost y customPosts para obtener datos de CPT, tanto para CPTs que están mapeados al esquema (como Post y Page) como para los que no (como un CPT de algún plugin). Como los resultados pueden incluir entidades de distintos tipos, estos campos devuelven el tipo CustomPostUnion.

Campos de Custom Post en el esquema
Gato GraphQL hace una clara distinción entre cuándo un custom post es un "custom post", y no directamente un "post".
Por ejemplo, se puede añadir un comentario a un post, pero también a una página y a un CPT, por lo que el tipo Comment tiene el campo customPost: CustomPostUnion! para recuperar la entidad donde se añadió el comentario, en lugar del campo post: Post!.

Por eso también el campo customPosts recibe el argumento customPostTypes en lugar de postTypes.
CPTs mapeados al esquema
Hay CPTs que han sido mapeados al esquema (como Post y Page para representar los CPTs "post" y "page"). En este caso, la consulta se resolverá usando el tipo GraphQL correspondiente para ese CPT.
Al obtener resultados de un union type, necesitamos especificar los campos a recuperar mediante fragments. Estos pueden evaluarse sobre la interfaz CustomPost, que está implementada por todos los tipos de CPT, o sobre cada tipo individual, como Post o Page.
En la consulta de abajo, obtenemos custom posts con los CPTs "post" y "page". Mostramos sus campos a través de 3 fragments, que evalúan si la entidad implementa CustomPost, o es de tipo Post o Page:
query {
customPosts(filter: { customPostTypes: ["post", "page"] }) {
...CustomPostProps
...PostProps
...PageProps
}
}
fragment CustomPostProps on CustomPost {
__typename
title
excerpt
url
dateStr(format: "d/m/Y")
}
fragment PostProps on Post {
tags {
id
name
}
}
fragment PageProps on Page {
author {
id
name
}
}CPTs no mapeados al esquema
Cuando un CPT aún no ha sido mapeado al esquema (como "attachment", "revision" o "nav_menu_item", o cualquier CPT instalado por algún plugin), seguimos usando los campos customPost y customPosts, y debemos pasar el nombre del CPT correspondiente bajo el argumento de campo filter.customPostTypes.
Como sus tipos no existen en el esquema, sus datos se recuperarán mediante el tipo GenericCustomPost, que contiene todas las propiedades comunes a los CPTs (title, content, excerpt, date, etc.).

En la consulta de abajo, obtenemos custom posts para una variedad de CPTs:
query {
customPosts(
filter:{
customPostTypes: [
"page",
"nav_menu_item",
"wp_block",
"wp_global_styles"
]
}
) {
... on CustomPost {
id
title
customPostType
status
}
__typename
}
}Permitir el acceso a Custom Post Types
Los CPTs deben ser explícitamente autorizados para poder consultarse, como se explica en la guía Permitir el acceso a Custom Post Types.
Consultar custom posts
Los tipos GraphQL para CPTs que han sido mapeados al esquema (como "post" => Post y "page" => Page) se incorporan directamente en CustomPostUnion.
Para cualquier CPT que no haya sido modelado en el esquema (como "attachment", "revision" o "nav_menu_item", o cualquier CPT instalado por algún plugin), sus datos se accederán mediante el tipo GenericCustomPost.
Indicamos los CPTs a recuperar mediante el argumento de campo filter.customPostTypes, que recibe una lista de cadenas, con los nombres de CPT tal como están definidos en WordPress (como "post", "page", etc.). Por ejemplo:
query {
customPosts(
filter: { customPostTypes: ["some-custom-cpt"] }
) {
... on CustomPost {
id
title
}
}
}Esta consulta recupera entradas de varios CPTs:
query {
customPosts(
filter: {
customPostTypes: [
"post",
"page",
"attachment",
"nav_menu_item",
"custom_css",
"revision"
],
status: [
publish,
inherit,
auto_draft
]
}
) {
id
title
content
status
customPostType
__typename
}
}Como todos los Custom Posts implementan la interfaz CustomPost, podemos recuperar datos de CustomPostUnion usando una referencia a un fragment o un inline fragment:
query {
comments {
id
date
content
customPost {
__typename
...on CustomPost {
id
title
url
}
}
}
}Si sabemos que el comentario fue añadido a un post, también podemos consultar campos específicos del Post:
query {
comments {
id
date
content
customPost {
__typename
...on CustomPost {
id
title
url
}
...on Post {
categoryNames
}
}
}
}Filtrar CPTs por una taxonomía personalizada
Un custom post type puede tener taxonomías personalizadas (etiquetas y categorías) asociadas. Por ejemplo, un CPT "product" puede tener asociadas la taxonomía de categoría "product-cat" y la taxonomía de etiqueta "product-tag".
Podemos filtrar resultados por estas taxonomías asociadas, mediante los inputs tags y categories en el input filter.
En la consulta de abajo, obtenemos custom posts filtrando por categoría:
query {
customPosts(
filter: {
categories: {
includeBy: {
ids: [26, 28]
}
taxonomy: "product-cat"
}
}
) {
... on CustomPost {
id
title
}
... on GenericCustomPost {
categories(taxonomy: "product-cat") {
id
}
}
}
}Obtener datos personalizados de CPT
Usando GenericCustomPost, solo podemos solicitar aquellos campos que son comunes a todos los CPTs; no se soporta obtener datos personalizados de algún CPT (como obtener los datos de precio para un CPT personalizado "product").
Para obtener datos personalizados de CPT, en su lugar, necesitamos crear los resolvers correspondientes, en código PHP, para mapear el CPT al esquema:
- Crear un tipo
Product - Adjuntarle un campo
price
Ahora, el tipo CustomPostUnion (devuelto por Root.customPosts) resolverá todas las entradas de este CPT al tipo Product.
query {
customPosts(
filter: {
customPostTypes: "product"
}
) {
__typename
...on CustomPost { # interface implemented by all CPT types
id
title
customPostType
status
}
...on Product { # custom CPT type
price # custom field
}
}
}Adicionalmente podemos crear el campo Root.products: [Product!], y usarlo directamente:
query {
products {
__typename # Product
id
title
status
price # custom field
}
}Mutar datos personalizados de CPT
En cuanto a los CPTs que no requieren campos adicionales sobre los del tipo Post, puedes usar tanto las mutaciones createCustomPost como updateCustomPost sin miedo ni reservas.
Por ejemplo, un CPT MyPortfolio que use los campos estándar title y content, y no tenga campos adicionales, puede gestionarse completamente mediante estas mutaciones.
Esta consulta crea una entrada para el CPT "my-portfolio":
mutation {
createCustomPost(
input: {
customPostType: "my-portfolio"
title: "My photograph"
contentAs: { html: "This is my photo, check it out." }
}
) {
status
errors {
__typename
...on ErrorPayload {
message
}
...on GenericErrorPayload {
code
}
}
customPost {
__typename
...on CustomPost {
id
title
content
}
}
}
}Esta consulta actualiza el título y el contenido para ese mismo CPT:
mutation {
updateCustomPost(input: {
id: 1
customPostType: "my-portfolio"
title: "Updated title"
contentAs: { html: "Updated content" }
}) {
status
errors {
__typename
...on ErrorPayload {
message
}
}
customPost {
__typename
...on CustomPost {
id
title
content
}
}
}
}Los custom post types proporcionados por plugins de terceros pueden necesitar ser creados (y posiblemente actualizados también) únicamente por el plugin correspondiente.
Esto es porque pueden tener sus datos personalizados (ya sea en wp_postmeta o en una tabla propietaria) que también necesitan ser añadidos, y de los que Gato GraphQL no es consciente.
Para gestionar estos CPTs apropiadamente, debe crearse una integración correspondiente entre ese plugin y Gato GraphQL, para proporcionar el mapeo de todos los campos del CPT.
Por ejemplo, podemos usar el campo Root.updateCustomPost para traducir y actualizar el título y contenido de un producto de WooCommerce (es decir, del CPT Product). Sin embargo, no podemos crear un producto de WooCommerce; para eso, debemos usar la correspondiente extensión "WooCommerce for Gato GraphQL".