Để lấy tất cả trang con (bao gồm cả cấp 1, cấp 2, cấp 3,...) của một trang cụ thể trong WordPress
Để lấy tất cả trang con (bao gồm cả cấp 1, cấp 2, cấp 3,...) của một trang cụ thể trong WordPress bằng GraphQL, bạn cần sử dụng plugin như WPGraphQL, và truy vấn phải sử dụng đệ quy (nếu được hỗ trợ) hoặc truy cập qua các cấp con cụ thể.
Tuy nhiên, WPGraphQL không hỗ trợ đệ quy tự động, nên bạn phải lặp các cấp con thủ công nếu số cấp đã biết. Dưới đây là ví dụ minh họa:
Muốn trích xuất tất cả các trang con (bao gồm cả các cấp độ sâu hơn như "Test 2.1", "Test 2.2") từ kết quả GraphQL đã cung cấp và đưa chúng vào một mảng phẳng.
Dưới đây là cách bạn có thể thực hiện điều đó bằng JavaScript (hoặc ngôn ngữ lập trình tương tự) để xử lý dữ liệu JSON đã nhận được:
const graphQLResult = {
"data": {
"page": {
"id": "cG9zdDo1OA==",
"uri": "/en/test/",
"children": {
"edges": [
{
"node": {
"id": "cG9zdDo4NQ==",
"excerpt": "",
"title": "Test 1",
"children": {
"nodes": [
{
"id": "cG9zdDo5MA==",
"excerpt": "",
"featuredImage": null,
"title": "Test 2.2"
},
{
"id": "cG9zdDo4Nw==",
"excerpt": "",
"featuredImage": null,
"title": "Test 2.1"
}
]
}
}
}
]
}
}
}
};
function getAllChildren(pageData) {
const childrenArray = [];
function traverseChildren(nodes) {
if (!nodes) {
return;
}
nodes.forEach(node => {
// Thêm thông tin của trang con hiện tại vào mảng
childrenArray.push({
id: node.id,
excerpt: node.excerpt,
title: node.title,
featuredImage: node.featuredImage // Bao gồm featuredImage nếu có
});
// Nếu có các trang con tiếp theo, đệ quy
if (node.children && node.children.nodes) {
traverseChildren(node.children.nodes);
}
});
}
// Bắt đầu duyệt từ các con trực tiếp của trang "test"
if (graphQLResult.data.page && graphQLResult.data.page.children && graphQLResult.data.page.children.edges) {
graphQLResult.data.page.children.edges.forEach(edge => {
// Đảm bảo rằng node tồn tại trước khi xử lý
if (edge.node) {
// Thêm trang con trực tiếp (Test 1)
childrenArray.push({
id: edge.node.id,
excerpt: edge.node.excerpt,
title: edge.node.title,
featuredImage: edge.node.featuredImage
});
// Duyệt các con của Test 1 (Test 2.1, Test 2.2)
if (edge.node.children && edge.node.children.nodes) {
traverseChildren(edge.node.children.nodes);
}
}
});
}
return childrenArray;
}
const allChildPages = getAllChildren(graphQLResult);
console.log(allChildPages);Kết quả đầu ra (từ console.log(allChildPages)):
Giải thích:
graphQLResult: Đây là đối tượng JSON chứa kết quả từ truy vấn GraphQL của bạn.getAllChildren(pageData):Hàm này sẽ nhận đối tượng kết quả GraphQL làm đầu vào.
childrenArray: Một mảng trống để lưu trữ tất cả các trang con đã tìm thấy.traverseChildren(nodes): Đây là một hàm đệ quy.Nó duyệt qua từng
nodetrong danh sáchnodesđược cung cấp.Với mỗi
node, nó lấy các thông tin cần thiết (id,excerpt,title,featuredImage) và thêm vàochildrenArray.Nếu
nodeđó có thêmchildren(tức là nó có các trang con riêng), hàmtraverseChildrensẽ được gọi lại vớinodescủa các trang con đó, tạo ra quá trình đệ quy để duyệt qua tất cả các cấp.
Logic chính:
Đầu tiên, nó kiểm tra xem
graphQLResult.data.pagevà cácchildren.edgescó tồn tại hay không.Sau đó, nó duyệt qua các
edgetrongchildren.edges(đây là các trang con trực tiếp của "Test", trong trường hợp này là "Test 1").Nó thêm "Test 1" vào
childrenArray.Cuối cùng, nó gọi
traverseChildrenđể xử lý các trang con của "Test 1" (là "Test 2.1" và "Test 2.2"), đảm bảo rằng tất cả các cấp độ đều được đưa vào mảng.
Cách tiếp cận này hiệu quả để làm phẳng cấu trúc cây và lấy tất cả các trang con vào một mảng duy nhất, dễ dàng để xử lý tiếp.
Khai báo với typescript
Bạn muốn khai báo hàm getAllChildren với TypeScript, dựa trên cấu trúc dữ liệu GraphQL mà bạn đã cung cấp trước đó. Hàm này sẽ duyệt đệ quy qua các trang con để thu thập tất cả chúng vào một mảng phẳng.
Dưới đây là cách bạn có thể khai báo và triển khai hàm getAllChildren bằng TypeScript:
Khai báo Type và Hàm getAllChildren
getAllChildrenĐể khai báo hàm này một cách rõ ràng trong TypeScript, trước tiên chúng ta cần định nghĩa các interface (kiểu dữ liệu) cho cấu trúc dữ liệu mà GraphQL trả về. Điều này giúp TypeScript hiểu rõ hình dạng của dữ liệu và cung cấp tính năng tự động hoàn thành, kiểm tra lỗi tĩnh.
TypeScript
Giải thích:
Định nghĩa Interfaces (
PageNode,GraphQLPageResult, v.v.):Đây là bước quan trọng nhất của TypeScript. Chúng ta tạo ra các "khuôn mẫu" để mô tả chính xác cấu trúc của dữ liệu mà bạn mong đợi từ GraphQL.
PageNodelà interface trung tâm, mô tả một đối tượng trang với các thuộc tính nhưid,title,excerpt,featuredImage, và quan trọng nhất làchildren.Thuộc tính
childrentrongPageNodeđược định nghĩa đệ quy để có thể chứa một mảng cácPageNodekhác, phản ánh cấu trúc phân cấp. Tôi đã bao gồm cảnodesvàedgesđể phù hợp với các định dạng trả về khác nhau của WPGraphQL.GraphQLPageResultlà interface bao bọc toàn bộ kết quả GraphQL, đảm bảo cấu trúcdata.pageđược xác định.
Hàm
getAllChildren(graphQLResult: GraphQLPageResult): PageNode[]:Kiểu tham số: Hàm nhận một đối tượng
graphQLResultcó kiểuGraphQLPageResult. TypeScript sẽ kiểm tra xem đối tượng bạn truyền vào có khớp với cấu trúc này không.Kiểu trả về: Hàm được khai báo sẽ trả về một mảng các
PageNode(PageNode[]).childrenArray: PageNode[] = []: Mảng này được khai báo với kiểuPageNode[], đảm bảo rằng chỉ các đối tượng khớp vớiPageNodemới có thể được thêm vào.Hàm
traverseChildren(nodes: PageNode[] | undefined):Đây là hàm đệ quy được sử dụng để duyệt qua các cấp độ con.
Tham số
nodescó kiểuPageNode[] | undefinedđể xử lý trường hợp không có node nào.Khi
childrenArray.push(node)được gọi, TypeScript đảm bảo rằngnodekhớp vớiPageNode.Logic kiểm tra
node.children && node.children.nodeshoặcnode.children && node.children.edgesgiúp hàm xử lý cả hai dạng trả về củachildren(trực tiếpnodeshoặc quaedges).
Bằng cách sử dụng các interface này, bạn sẽ nhận được sự hỗ trợ mạnh mẽ từ TypeScript, giúp phát hiện lỗi cú pháp, lỗi logic sớm hơn trong quá trình phát triển, và làm cho mã nguồn của bạn dễ đọc và bảo trì hơn.
Bạn muốn chuyển đổi cấu trúc dữ liệu GraphQL phức tạp thành một mảng phẳng các đối tượng Product đơn giản hơn, phù hợp với interface Product mà bạn đã định nghĩa.
Product đơn giản hơn, phù hợp với interface Product mà bạn đã định nghĩa.Dưới đây là hàm TypeScript để thực hiện việc chuyển đổi này, bao gồm cả việc xử lý ảnh đại diện (featuredImage).
TypeScript
Giải thích các thay đổi và logic:
Cập nhật Interfaces GraphQL:
FeaturedImageGraphQL: Đã đổi tên để tránh nhầm lẫn với trườngimgtrongProduct.Đảm bảo
__typenameđược bao gồm ở tất cả các cấp nơi nó xuất hiện trong dữ liệu của bạn.
Hàm
convertGraphQLToProducts(graphQLResult: GraphQLPageResult): Product[]:products: Product[] = []: Khởi tạo một mảng rỗng để lưu trữ các đối tượngProductđã chuyển đổi.processPageNode(pageNode: PageNode): Đây là hàm đệ quy chính:Nó nhận một
PageNodelàm đối số.Lấy
img(sourceUrl):TypeScriptDòng này sử dụng optional chaining (
?.) để truy cập an toàn vàofeaturedImage,nodevàsourceUrl. Nếu bất kỳ phần nào trên đường dẫn lànullhoặcundefined, nó sẽ trả vềundefined, và sau đó toán tử|| ''sẽ gán một chuỗi rỗng.Gán
category:Tôi đã thêm một logic giả định để gán
categorydựa trêntitlecủa trang (if (pageNode.title.includes('Test 1')) { category = 'category-A'; }).Bạn cần thay đổi logic này để phù hợp với cách bạn muốn phân loại các sản phẩm của mình. Ví dụ, bạn có thể có một trường custom field trong WordPress lưu trữ category của sản phẩm, và bạn sẽ cần truy vấn trường đó qua GraphQL để lấy thông tin category.
Thêm vào
productsarray: Một đối tượngProductmới được tạo vớiid,title(từpageNode.title),img(từimageUrl), vàcategoryvà đượcpushvào mảngproducts.Đệ quy cho
children: Hàm này sau đó kiểm trapageNode.childrenvà gọi đệ quyprocessPageNodecho tất cả các trang con (dù chúng nằm trongnodeshayedges).
Logic bắt đầu:
Hàm bắt đầu bằng cách lấy
rootPage(graphQLResult.data.page).Nó sau đó kiểm tra
rootPage.childrenvà bắt đầu quá trình đệ quyprocessPageNodecho tất cả các trang con trực tiếp của trang gốc.Nếu bạn muốn bản thân trang gốc (ví dụ "Test") cũng được chuyển đổi thành một "Product" và thêm vào danh sách, bạn chỉ cần gọi
processPageNode(rootPage);trước khi xử lý các con của nó. Hiện tại, nó chỉ xử lý các trang con của "Test".
Với hàm này, bạn có thể biến dữ liệu GraphQL phân cấp của mình thành một mảng phẳng các đối tượng Product dễ dàng quản lý trong ứng dụng Next.js của bạn.
Generate Audio Overview
src\graphql\queries.ts
Last updated
Was this helpful?