Praca z
Praca zCustom Posts

Custom Posts

Używamy pól customPost i customPosts do pobierania danych CPT, zarówno dla CPT zmapowanych w schemacie (takich jak Post i Page), jak i tych, które nie są (np. CPT z jakiegoś pluginu). Ponieważ wyniki mogą zawierać encje różnych typów, pola te zwracają typ CustomPostUnion.

Typ CustomPostUnion

Pola Custom Post w schemacie

Gato GraphQL wyraźnie rozróżnia, kiedy custom post jest „custom postem", a nie bezpośrednio „postem".

Na przykład komentarz może zostać dodany do posta, ale także do strony i do CPT; dlatego typ Comment posiada pole customPost: CustomPostUnion! do pobierania encji, do której dodano komentarz, zamiast pola post: Post!.

Typ Comment

To również dlatego pole customPosts przyjmuje argument customPostTypes zamiast postTypes.

CPT zmapowane w schemacie

Istnieją CPT, które zostały zmapowane w schemacie (takie jak Post i Page reprezentujące CPT "post" i "page"). W tym przypadku query zostanie rozwiązane przy użyciu odpowiedniego typu GraphQL dla danego CPT.

Przy pobieraniu wyników z typu union musimy wskazać pola do pobrania za pomocą fragmentów. Mogą one być oceniane na interfejsie CustomPost, który jest implementowany przez wszystkie typy CPT, lub na każdym indywidualnym typie, takim jak Post czy Page.

W poniższej query pobieramy custom posts z CPT "post" i "page". Wyświetlamy ich pola za pomocą 3 fragmentów, które sprawdzają, czy encja implementuje CustomPost, lub jest typu Post albo 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
  }
}

CPT niezmapowane w schemacie

Gdy CPT nie został jeszcze zmapowany w schemacie (jak "attachment", "revision" czy "nav_menu_item", lub dowolny CPT zainstalowany przez jakiś plugin), nadal używamy pól customPost i customPosts, i musimy przekazać odpowiednią nazwę CPT w argumencie pola filter.customPostTypes.

Ponieważ ich typy nie istnieją w schemacie, ich dane będą pobierane za pomocą typu GenericCustomPost, który zawiera wszystkie właściwości wspólne dla CPT (title, content, excerpt, date itp.).

Generyczny Custom Post

W poniższej query pobieramy custom posts dla różnych CPT:

query {
  customPosts(
    filter:{
      customPostTypes: [
        "page",
        "nav_menu_item",
        "wp_block",
        "wp_global_styles"
      ]
    }
  ) {
    ... on CustomPost {
      id
      title
      customPostType
      status
    }
    __typename
  }
}

Zezwalanie na dostęp do Custom Post Types

CPT muszą być jawnie dopuszczone do odpytywania, jak wyjaśniono w przewodniku Zezwalanie na dostęp do Custom Post Types.

Odpytywanie custom posts

Typy GraphQL dla CPT, które zostały zmapowane w schemacie (takie jak "post" => Post i "page" => Page), są włączane bezpośrednio do CustomPostUnion.

Dla dowolnego CPT, który nie został zamodelowany w schemacie (jak "attachment", "revision" czy "nav_menu_item", lub dowolny CPT zainstalowany przez jakiś plugin), dostęp do jego danych będzie odbywał się za pomocą typu GenericCustomPost.

Wskazujemy CPT do pobrania za pomocą argumentu pola filter.customPostTypes, który przyjmuje listę ciągów znakowych z nazwami CPT zdefiniowanymi w WordPress (takimi jak "post", "page" itp.). Na przykład:

query {
  customPosts(
    filter: { customPostTypes: ["some-custom-cpt"] }
  ) {
    ... on CustomPost {
      id
      title
    }
  }
}

Ta query pobiera wpisy z wielu CPT:

query {
  customPosts(
    filter: {
      customPostTypes: [
        "post",
        "page",
        "attachment",
        "nav_menu_item",
        "custom_css",
        "revision"
      ],
      status: [
        publish,
        inherit,
        auto_draft
      ]
    }
  ) {
    id
    title
    content
    status
    customPostType
    __typename
  }
}

Ponieważ wszystkie Custom Posts implementują interfejs CustomPost, możemy pobierać dane z CustomPostUnion używając odwołania do fragmentu lub fragmentu inline:

query {
  comments {
    id
    date
    content
    customPost {
      __typename
      ...on CustomPost {
        id
        title
        url
      }
    }
  }
}

Jeśli wiemy, że komentarz został dodany do posta, możemy również odpytywać pola specyficzne dla Post:

query {
  comments {
    id
    date
    content
    customPost {
      __typename
      ...on CustomPost {
        id
        title
        url
      }
      ...on Post {
        categoryNames
      }
    }
  }
}

Filtrowanie CPT według niestandardowej taksonomii

Custom post type może mieć powiązane z nim niestandardowe taksonomie (tagi i kategorie). Na przykład CPT "product" może mieć powiązaną taksonomię kategorii "product-cat" i taksonomię tagów "product-tag".

Możemy filtrować wyniki według tych powiązanych taksonomii za pomocą inputów tags i categories w inpucie filter.

W poniższej query pobieramy custom posts filtrując według kategorii:

query {
  customPosts(
    filter: {
      categories: {
        includeBy: {
          ids: [26, 28]
        }
        taxonomy: "product-cat"
      }
    }
  ) {
    ... on CustomPost {
      id
      title
    }
    ... on GenericCustomPost {
      categories(taxonomy: "product-cat") {
        id
      }
    }
  }
}

Pobieranie niestandardowych danych CPT

Używając GenericCustomPost, możemy żądać tylko tych pól, które są wspólne dla wszystkich CPT; pobieranie niestandardowych danych z jakiegoś CPT nie jest obsługiwane (np. pobieranie danych cenowych z niestandardowego CPT "product").

Aby pobierać niestandardowe dane CPT, musimy zamiast tego utworzyć odpowiednie resolvery w kodzie PHP, aby zmapować CPT do schematu:

  • Utwórz typ Product
  • Dołącz do niego pole price

Teraz typ CustomPostUnion (zwracany przez Root.customPosts) będzie rozwiązywał wszystkie wpisy z tego CPT do typu 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
    }
  }
}

Możemy dodatkowo utworzyć pole Root.products: [Product!] i używać go bezpośrednio:

query {
  products {
    __typename # Product
    id
    title
    status
    price # custom field
  }
}

Mutowanie niestandardowych danych CPT

Jeśli chodzi o CPT, które nie wymagają żadnych dodatkowych pól poza polami z typu Post, możesz używać zarówno mutacji createCustomPost, jak i updateCustomPost bez żadnych obaw czy ograniczeń.

Na przykład CPT MyPortfolio używający standardowych pól title i content i nieposiadający żadnych dodatkowych pól może być w pełni zarządzany za pomocą tych mutacji.

Ta query tworzy wpis dla 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
      }
    }
  }
}

Ta query aktualizuje tytuł i treść dla tego samego 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 dostarczane przez zewnętrzne pluginy mogą wymagać, aby były tworzone (a możliwe, że też aktualizowane) wyłącznie przez odpowiedni plugin.

Dzieje się tak, ponieważ mogą posiadać własne dane (w wp_postmeta lub w zastrzeżonej tabeli), które również muszą być dodane, a o których Gato GraphQL nie ma wiedzy.

Aby właściwie zarządzać tymi CPT, należy stworzyć odpowiednią integrację między tym pluginem a Gato GraphQL, która zapewni mapowanie wszystkich pól dla CPT.

Na przykład możemy użyć pola Root.updateCustomPost do tłumaczenia i aktualizacji tytułu i treści produktu WooCommerce (tj. z CPT Product). Nie możemy jednak tworzyć produktów WooCommerce; w tym celu musimy użyć odpowiedniego rozszerzenia „WooCommerce for Gato GraphQL".