Custom Posts
Chúng ta sử dụng các trường customPost và customPosts để lấy dữ liệu CPT, cả cho các CPT đã được ánh xạ vào schema (như Post và Page) lẫn những loại chưa được ánh xạ (như CPT từ một plugin nào đó). Vì kết quả có thể bao gồm các thực thể thuộc nhiều kiểu khác nhau, các trường này trả về kiểu CustomPostUnion.

Các trường Custom Post trong schema
Gato GraphQL phân biệt rõ ràng khi nào một custom post là "custom post" và khi nào nó không trực tiếp là "post".
Ví dụ, một bình luận có thể được thêm vào một post, nhưng cũng có thể thêm vào một trang và vào một CPT, do đó kiểu Comment có trường customPost: CustomPostUnion! để lấy thực thể nơi bình luận được thêm vào, thay vì trường post: Post!.

Đó cũng là lý do tại sao trường customPosts nhận đối số customPostTypes thay vì postTypes.
Các CPT được ánh xạ vào schema
Có những CPT đã được ánh xạ vào schema (như Post và Page để đại diện cho các CPT "post" và "page"). Trong trường hợp này, query sẽ được giải quyết bằng kiểu GraphQL tương ứng cho CPT đó.
Khi lấy kết quả từ một kiểu union, chúng ta cần chỉ định các trường cần lấy thông qua các fragment. Chúng có thể được đánh giá trên interface CustomPost, được triển khai bởi tất cả các kiểu CPT, hoặc trên từng kiểu riêng lẻ, chẳng hạn như Post hoặc Page.
Trong query bên dưới, chúng ta lấy các custom post với các CPT "post" và "page". Chúng ta hiển thị các trường của chúng thông qua 3 fragment, đánh giá xem thực thể có triển khai CustomPost, hay thuộc kiểu Post hoặc 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
}
}Các CPT chưa được ánh xạ vào schema
Khi một CPT chưa được ánh xạ vào schema (như "attachment", "revision" hoặc "nav_menu_item", hoặc bất kỳ CPT nào được cài đặt bởi một plugin), chúng ta vẫn sử dụng các trường customPost và customPosts, và phải truyền tên CPT tương ứng trong đối số trường filter.customPostTypes.
Vì các kiểu của chúng không tồn tại trong schema, dữ liệu của chúng sẽ được lấy thông qua kiểu GenericCustomPost, chứa tất cả các thuộc tính chung của các CPT (title, content, excerpt, date, v.v.).

Trong query bên dưới, chúng ta lấy các custom post cho nhiều loại CPT:
query {
customPosts(
filter:{
customPostTypes: [
"page",
"nav_menu_item",
"wp_block",
"wp_global_styles"
]
}
) {
... on CustomPost {
id
title
customPostType
status
}
__typename
}
}Cho phép truy cập vào Custom Post Types
Các CPT phải được cho phép truy cập một cách rõ ràng, như được giải thích trong hướng dẫn Cho phép truy cập vào Custom Post Types.
Truy vấn custom posts
Các kiểu GraphQL cho các CPT đã được ánh xạ vào schema (như "post" => Post và "page" => Page) được tích hợp trực tiếp vào CustomPostUnion.
Đối với bất kỳ CPT nào chưa được mô hình hóa trong schema (như "attachment", "revision" hoặc "nav_menu_item", hoặc bất kỳ CPT nào được cài đặt bởi một plugin), dữ liệu của chúng sẽ được truy cập qua kiểu GenericCustomPost.
Chúng ta chỉ định các CPT cần lấy thông qua đối số trường filter.customPostTypes, nhận một danh sách các chuỗi, với tên CPT được định nghĩa trong WordPress (như "post", "page", v.v.). Ví dụ:
query {
customPosts(
filter: { customPostTypes: ["some-custom-cpt"] }
) {
... on CustomPost {
id
title
}
}
}Query này lấy các mục từ nhiều 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
}
}Vì tất cả Custom Posts đều triển khai interface CustomPost, chúng ta có thể lấy dữ liệu từ CustomPostUnion bằng cách sử dụng tham chiếu fragment hoặc fragment nội tuyến:
query {
comments {
id
date
content
customPost {
__typename
...on CustomPost {
id
title
url
}
}
}
}Nếu chúng ta biết rằng bình luận được thêm vào một post, chúng ta cũng có thể truy vấn các trường dành riêng cho Post:
query {
comments {
id
date
content
customPost {
__typename
...on CustomPost {
id
title
url
}
...on Post {
categoryNames
}
}
}
}Lọc CPT theo phân loại tùy chỉnh
Một custom post type có thể có các phân loại tùy chỉnh (tags và categories) được liên kết với chúng. Ví dụ, một CPT "product" có thể có phân loại danh mục "product-cat" và phân loại thẻ "product-tag" liên kết.
Chúng ta có thể lọc kết quả theo các phân loại liên kết này, thông qua các input tags và categories trong input filter.
Trong query bên dưới, chúng ta lấy các custom post được lọc theo danh mục:
query {
customPosts(
filter: {
categories: {
includeBy: {
ids: [26, 28]
}
taxonomy: "product-cat"
}
}
) {
... on CustomPost {
id
title
}
... on GenericCustomPost {
categories(taxonomy: "product-cat") {
id
}
}
}
}Lấy dữ liệu CPT tùy chỉnh
Sử dụng GenericCustomPost, chúng ta chỉ có thể yêu cầu những trường chung cho tất cả các CPT; việc lấy dữ liệu tùy chỉnh từ một CPT nào đó không được hỗ trợ (chẳng hạn như lấy dữ liệu giá cho một CPT tùy chỉnh "product").
Để lấy dữ liệu CPT tùy chỉnh, thay vào đó, chúng ta cần tạo các resolver tương ứng, bằng mã PHP, để ánh xạ CPT vào schema:
- Tạo một kiểu
Product - Gắn một trường
pricevào đó
Bây giờ, kiểu CustomPostUnion (được trả về bởi Root.customPosts) sẽ giải quyết tất cả các mục từ CPT này thành kiểu 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
}
}
}Chúng ta có thể tạo thêm trường Root.products: [Product!], và sử dụng nó trực tiếp:
query {
products {
__typename # Product
id
title
status
price # custom field
}
}Thay đổi dữ liệu CPT tùy chỉnh
Đối với các CPT không yêu cầu bất kỳ trường bổ sung nào so với các trường từ kiểu Post, bạn có thể sử dụng cả hai mutation createCustomPost và updateCustomPost mà không cần lo lắng hay hạn chế gì.
Ví dụ, một CPT MyPortfolio sử dụng các trường tiêu chuẩn title và content, và không có trường bổ sung nào, có thể được quản lý hoàn toàn thông qua các mutation này.
Query này tạo một mục cho 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
}
}
}
}Query này cập nhật tiêu đề và nội dung cho cùng 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
}
}
}
}Các custom post type được cung cấp bởi các plugin bên thứ ba có thể cần được tạo (và có thể cả cập nhật) chỉ bởi plugin tương ứng.
Điều này là do chúng có thể có dữ liệu tùy chỉnh riêng (trong wp_postmeta hoặc trong một bảng độc quyền) cũng cần được thêm vào, và Gato GraphQL không biết về điều này.
Để quản lý các CPT này một cách phù hợp, cần tạo một tích hợp tương ứng giữa plugin đó và Gato GraphQL, để cung cấp ánh xạ cho tất cả các trường của CPT.
Ví dụ, chúng ta có thể sử dụng trường Root.updateCustomPost để dịch và cập nhật tiêu đề và nội dung của một sản phẩm WooCommerce (tức là từ CPT Product). Tuy nhiên, chúng ta không thể tạo một sản phẩm WooCommerce; để làm điều đó, chúng ta phải sử dụng extension "WooCommerce for Gato GraphQL" tương ứng.