Custom Posts
Usamos os campos customPost e customPosts para buscar dados de CPTs, tanto para CPTs mapeados no schema (como Post e Page) quanto para aqueles que não estão (como um CPT de algum plugin). Como os resultados podem incluir entidades de tipos diferentes, esses campos retornam o tipo CustomPostUnion.

Campos Custom Post no schema
Gato GraphQL faz uma distinção clara entre quando um custom post é um "custom post" e não diretamente um "post".
Por exemplo, um comentário pode ser adicionado a um post, mas também a uma página e a um CPT; por isso o tipo Comment possui o campo customPost: CustomPostUnion! para recuperar a entidade onde o comentário foi adicionado, em vez do campo post: Post!.

É também por essa razão que o campo customPosts recebe o argumento customPostTypes em vez de postTypes.
CPTs mapeados no schema
Existem CPTs que foram mapeados no schema (como Post e Page para representar os CPTs "post" e "page"). Nesse caso, a query será resolvida usando o tipo GraphQL correspondente a esse CPT.
Ao buscar resultados de um tipo union, precisamos especificar os campos a recuperar por meio de fragments. Esses podem ser avaliados na interface CustomPost, que é implementada por todos os tipos de CPT, ou em cada tipo individual, como Post ou Page.
Na query abaixo, buscamos custom posts com os CPTs "post" e "page". Exibimos seus campos por meio de 3 fragments, que avaliam se a entidade implementa CustomPost, ou é do tipo Post ou 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 não mapeados no schema
Quando um CPT ainda não foi mapeado no schema (como "attachment", "revision" ou "nav_menu_item", ou qualquer CPT instalado por algum plugin), ainda usamos os campos customPost e customPosts, e devemos passar o nome do CPT correspondente no argumento de campo filter.customPostTypes.
Como seus tipos não existem no schema, seus dados serão recuperados por meio do tipo GenericCustomPost, que contém todas as propriedades comuns aos CPTs (title, content, excerpt, date, etc.).

Na query abaixo, buscamos custom posts para uma variedade de CPTs:
query {
customPosts(
filter:{
customPostTypes: [
"page",
"nav_menu_item",
"wp_block",
"wp_global_styles"
]
}
) {
... on CustomPost {
id
title
customPostType
status
}
__typename
}
}Permitindo acesso aos Custom Post Types
Os CPTs devem ser explicitamente autorizados a ser consultáveis, conforme explicado no guia Permitindo acesso aos Custom Post Types.
Consultando custom posts
Os tipos GraphQL para CPTs que foram mapeados no schema (como "post" => Post e "page" => Page) são incorporados diretamente em CustomPostUnion.
Para qualquer CPT que não foi modelado no schema (como "attachment", "revision" ou "nav_menu_item", ou qualquer CPT instalado por algum plugin), seus dados serão acessados por meio do tipo GenericCustomPost.
Indicamos os CPTs a recuperar por meio do argumento de campo filter.customPostTypes, que recebe uma lista de strings com os nomes dos CPTs conforme definidos no WordPress (como "post", "page", etc.). Por exemplo:
query {
customPosts(
filter: { customPostTypes: ["some-custom-cpt"] }
) {
... on CustomPost {
id
title
}
}
}Esta query recupera entradas de múltiplos 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 os Custom Posts implementam a interface CustomPost, podemos recuperar dados de CustomPostUnion usando uma referência a um fragment ou um fragment inline:
query {
comments {
id
date
content
customPost {
__typename
...on CustomPost {
id
title
url
}
}
}
}Se soubermos que o comentário foi adicionado a um post, também podemos consultar campos específicos do Post:
query {
comments {
id
date
content
customPost {
__typename
...on CustomPost {
id
title
url
}
...on Post {
categoryNames
}
}
}
}Filtrando CPTs por uma taxonomia personalizada
Um custom post type pode ter taxonomias personalizadas (tags e categorias) associadas a ele. Por exemplo, um CPT "product" pode ter associada a taxonomia de categoria "product-cat" e a taxonomia de tag "product-tag".
Podemos filtrar os resultados por essas taxonomias associadas, por meio dos inputs tags e categories no input filter.
Na query abaixo, buscamos custom posts filtrando por categoria:
query {
customPosts(
filter: {
categories: {
includeBy: {
ids: [26, 28]
}
taxonomy: "product-cat"
}
}
) {
... on CustomPost {
id
title
}
... on GenericCustomPost {
categories(taxonomy: "product-cat") {
id
}
}
}
}Buscando dados personalizados de CPT
Usando GenericCustomPost, podemos solicitar apenas os campos comuns a todos os CPTs; buscar dados personalizados de algum CPT não é suportado (como buscar os dados de preço de um CPT personalizado "product").
Para buscar dados personalizados de CPT, precisamos criar os resolvers correspondentes, em código PHP, para mapear o CPT ao schema:
- Criar um tipo
Product - Vincular um campo
pricea ele
Agora, o tipo CustomPostUnion (retornado por Root.customPosts) resolverá todas as entradas desse CPT para um 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
}
}
}Podemos ainda criar o campo Root.products: [Product!] e usá-lo diretamente:
query {
products {
__typename # Product
id
title
status
price # custom field
}
}Mutando dados personalizados de CPT
No que diz respeito aos CPTs que não requerem campos adicionais além dos do tipo Post, você pode usar tanto as mutations createCustomPost quanto updateCustomPost sem nenhum receio ou restrição.
Por exemplo, um CPT MyPortfolio que usa os campos padrão title e content, e não possui campos extras, pode ser totalmente gerenciado por meio dessas mutations.
Esta query cria uma entrada para o 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 query atualiza o título e o conteúdo para o mesmo 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
}
}
}
}Custom post types fornecidos por plugins de terceiros podem precisar ser criados (e possivelmente atualizados também) apenas pelo plugin correspondente.
Isso ocorre porque podem ter seus dados personalizados (em wp_postmeta ou em uma tabela proprietária) que também precisam ser adicionados, e dos quais Gato GraphQL não tem conhecimento.
Para gerenciar esses CPTs adequadamente, deve ser criada uma integração correspondente entre esse plugin e Gato GraphQL, que forneça o mapeamento de todos os campos do CPT.
Por exemplo, podemos usar o campo Root.updateCustomPost para traduzir e atualizar o título e o conteúdo de um produto WooCommerce (ou seja, do CPT Product). No entanto, não podemos criar um produto WooCommerce; para isso, devemos usar a extensão "WooCommerce for Gato GraphQL" correspondente.