Bài học 5: Tùy chỉnh nội dung cho người dùng khác nhau
Chúng ta có thể truy xuất phản hồi khác nhau trong một trường dựa trên một phần dữ liệu được truy vấn, chẳng hạn như vai trò của người dùng đang đăng nhập.
GraphQL query để tùy chỉnh nội dung cho người dùng khác nhau
GraphQL query này truy xuất nội dung bài viết, thêm liên kết "Chỉnh sửa bài viết này" ở cuối nội dung chỉ dành cho người dùng quản trị viên:
query InitializeDynamicVariables
@configureWarningsOnExportingDuplicateVariable(enabled: false)
{
isAdminUser: _echo(value: false)
@export(as: "isAdminUser")
@remove
}
query ExportConditionalVariables
@depends(on: "InitializeDynamicVariables")
{
me {
roleNames @remove
isAdminUser: _inArray(
value: "administrator",
array: $__roleNames
)
@export(as: "isAdminUser")
}
}
query RetrieveContentForAdminUser($postId: ID!)
@depends(on: "ExportConditionalVariables")
@include(if: $isAdminUser)
{
post(by: { id : $postId }) {
originalContent: content @remove
wpAdminEditURL @remove
content: _sprintf(
string: "%s<p><a href=\"%s\">%s</a></p>",
values: [
$__originalContent,
$__wpAdminEditURL,
"(Admin only) Edit post"
]
)
}
}
query RetrieveContentForNonAdminUser($postId: ID!)
@depends(on: "ExportConditionalVariables")
@skip(if: $isAdminUser)
{
post(by: { id : $postId }) {
content
}
}
query ExecuteAll
@depends(on: [
"RetrieveContentForAdminUser",
"RetrieveContentForNonAdminUser"
])
{
id @remove
}Đối với người dùng quản trị viên, phản hồi sẽ là:
{
"data": {
"user": {
"isAdminUser": true
},
"post": {
"content": "\n<p>Welcome to WordPress. This is your first post. Edit or delete it, then start writing!<\/p>\n<p><a href=\"https:\/\/mysite.com\/wp-admin\/post.php?post=1&action=edit\">(Admin only) Edit post<\/a><\/p>"
}
}
}Đối với người dùng không phải quản trị viên, phản hồi sẽ là:
{
"data": {
"user": {
"isAdminUser": false
},
"post": {
"content": "\n<p>Welcome to WordPress. This is your first post. Edit or delete it, then start writing!<\/p>\n"
}
}
}Để máy chủ GraphQL (với tất cả các điều kiện có thể có) tự động tính toán giá trị cần thiết cho một trường:
- Đơn giản hóa logic của ứng dụng, vì chỉ có một nguồn dữ liệu duy nhất, code trở nên DRY, và các client không cần triển khai logic tương ứng nữa
- Làm cho ứng dụng đáng tin cậy hơn, đặc biệt khi nhiều client truy cập dữ liệu từ máy chủ, vì các triển khai khác nhau của cùng một logic có thể không giống hệt nhau, dẫn đến các lỗi tiềm ẩn (đặc biệt hơn khi các client dựa trên các công nghệ khác nhau, chẳng hạn như JavaScript cho website, Java cho ứng dụng Android, Swift cho ứng dụng iPhone, và các ngôn ngữ khác)
Từng bước: tạo GraphQL query
Dưới đây là phân tích chi tiết về cách query hoạt động.
Xác định xem người dùng có phải là quản trị viên không
Query này kiểm tra xem người dùng đang đăng nhập có vai trò "administrator" không, và xuất điều kiện này vào biến động $isAdminUser:
query
{
me {
roleNames
isAdminUser: _inArray(
value: "administrator",
array: $__roleNames
)
@export(as: "isAdminUser")
}
}Thực thi có điều kiện các thao tác
Khi Thực thi Multiple Query được kích hoạt, các directive @include và @skip cũng có thể được áp dụng cho các thao tác. Bằng cách này, chúng ta có thể thực thi hay không thực thi một thao tác tùy thuộc vào giá trị của biến động nào đó.
Trong query bên dưới, chỉ một trong hai thao tác sẽ được thực thi:
RetrieveContentForAdminUserchỉ được thực thi khi$isAdminUserlàtrueRetrieveContentForNonAdminUserchỉ được thực thi khi$isAdminUserlàfalse
query RetrieveContentForAdminUser
@depends(on: "ExportConditionalVariables")
@include(if: $isAdminUser)
{
# ...
}
query RetrieveContentForNonAdminUser
@depends(on: "ExportConditionalVariables")
@skip(if: $isAdminUser)
{
# ...
}Hãy cung cấp hai phản hồi khác nhau cho trường content của bài viết tùy thuộc vào việc người dùng có phải là quản trị viên hay không:
- Thao tác đầu tiên sử dụng
contentlàm alias, và tính toán giá trị của trường một cách động, ghép nối các trườngoriginalContentvàwpAdminEditURLlại với nhau thông qua_sprintf - Thao tác thứ hai truy xuất trường
contenttrực tiếp
query RetrieveContentForAdminUser($postId: ID!)
@depends(on: "ExportConditionalVariables")
@include(if: $isAdminUser)
{
post(by: { id : $postId }) {
originalContent: content
wpAdminEditURL
content: _sprintf(
string: "%s<p><a href=\"%s\">%s</a></p>",
values: [
$__originalContent,
$__wpAdminEditURL,
"(Admin only) Edit post"
]
)
}
}
query RetrieveContentForNonAdminUser($postId: ID!)
@depends(on: "ExportConditionalVariables")
@skip(if: $isAdminUser)
{
post(by: { id : $postId }) {
content
}
}Thêm thao tác cần thực thi
Bây giờ chúng ta có hai thao tác có thể được thực thi, tuy nhiên chúng ta chỉ có thể cung cấp một ?operationName=... khi thực thi query.
Vì vậy, chúng ta thêm thao tác ExecuteAll phụ thuộc vào cả RetrieveContentForAdminUser và RetrieveContentForNonAdminUser, chứa trường đơn giản id (vì chúng ta phải truy vấn một thứ gì đó trong thao tác):
query ExecuteAll
@depends(on: [
"RetrieveContentForAdminUser",
"RetrieveContentForNonAdminUser"
])
{
id
}Gọi endpoint với ?operationName=ExecuteAll sẽ tải cả hai thao tác, tuy nhiên chỉ một trong số đó thực sự được thực thi.
Xóa dữ liệu không cần thiết
Bước cuối cùng là xóa tất cả các trường phụ trợ (và do đó chúng ta không cần in kết quả của chúng trong phản hồi) thông qua @remove.
GraphQL query đã được hợp nhất là:
query InitializeDynamicVariables
@configureWarningsOnExportingDuplicateVariable(enabled: false)
{
isAdminUser: _echo(value: false)
@export(as: "isAdminUser")
@remove
}
query ExportConditionalVariables
@depends(on: "InitializeDynamicVariables")
{
me {
roleNames @remove
isAdminUser: _inArray(
value: "administrator",
array: $__roleNames
)
@export(as: "isAdminUser")
}
}
query RetrieveContentForAdminUser($postId: ID!)
@depends(on: "ExportConditionalVariables")
@include(if: $isAdminUser)
{
post(by: { id : $postId }) {
originalContent: content @remove
wpAdminEditURL @remove
content: _sprintf(
string: "%s<p><a href=\"%s\">%s</a></p>",
values: [
$__originalContent,
$__wpAdminEditURL,
"(Admin only) Edit post"
]
)
}
}
query RetrieveContentForNonAdminUser($postId: ID!)
@depends(on: "ExportConditionalVariables")
@skip(if: $isAdminUser)
{
post(by: { id : $postId }) {
content
}
}
query ExecuteAll
@depends(on: [
"RetrieveContentForAdminUser",
"RetrieveContentForNonAdminUser"
])
{
id @remove
}