Trabalhando com
Trabalhando comCustom Posts

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.

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!.

Tipo Comment

É 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.).

Custom Post Genérico

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 price a 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.