การจัดการ Mutation Payload
ฟิลด์ mutation สามารถกำหนดค่าให้คืนค่าเป็นประเภทเอนทิตีใดประเภทหนึ่งใน 2 ประเภทต่อไปนี้
- ประเภท payload object
- คืนค่าเอนทิตีที่ถูก mutate โดยตรง
ประเภท Payload Object
ประเภท payload object ประกอบด้วยข้อมูลทั้งหมดที่เกี่ยวข้องกับ mutation ได้แก่
- สถานะของ mutation (สำเร็จหรือล้มเหลว)
- ข้อผิดพลาด (ถ้ามี) โดยใช้ประเภท GraphQL ที่แตกต่างกัน หรือ
- เอนทิตีที่ถูก mutate สำเร็จ
ตัวอย่างเช่น mutation updatePost คืนค่าออบเจ็กต์ประเภท PostUpdateMutationPayload และเราจำเป็นต้องคิวรีฟิลด์ post เพื่อดึงข้อมูลเอนทิตีโพสต์ที่อัปเดต
mutation UpdatePost {
updatePost(input: {
id: 1724,
title: "New title",
status: publish
}) {
# This is the status of the mutation: SUCCESS or FAILURE
status
errors {
__typename
...on ErrorPayload {
message
}
}
post {
id
title
# This is the status of the post: publish, pending, trash, etc
status
}
}
}payload object ช่วยให้เราสามารถแสดงข้อผิดพลาดได้ดียิ่งขึ้น แม้แต่การมีประเภท GraphQL ที่ไม่ซ้ำกันสำหรับข้อผิดพลาดแต่ละประเภท ซึ่งช่วยให้เราสามารถแสดงการตอบสนองที่แตกต่างกันสำหรับข้อผิดพลาดที่แตกต่างกันในแอปพลิเคชัน จึงปรับปรุงประสบการณ์ของผู้ใช้
ในตัวอย่างข้างต้น หากการดำเนินการสำเร็จ เราจะได้รับ
{
"data": {
"updatePost": {
"status": "SUCCESS",
"errors": null,
"post": {
"id": 1724,
"title": "Some title",
"status": "publish"
}
}
}
}หากผู้ใช้ไม่ได้เข้าสู่ระบบ เราจะได้รับ
{
"data": {
"updatePost": {
"status": "FAILURE",
"errors": [
{
"__typename": "UserIsNotLoggedInErrorPayload",
"message": "You must be logged in to create or update custom posts"
}
],
"post": null
}
}
}หากผู้ใช้ไม่มีสิทธิ์ในการแก้ไขโพสต์ เราจะได้รับ
{
"data": {
"updatePost": {
"status": "FAILURE",
"errors": [
{
"__typename": "LoggedInUserHasNoEditingCustomPostCapabilityErrorPayload",
"message": "Your user doesn't have permission for editing custom posts."
}
],
"post": null
}
}
}ในโหมดนี้ GraphQL schema จะมีประเภท MutationPayload, MutationErrorPayloadUnion และ ErrorPayload เพิ่มเติมจำนวนมาก ทำให้ schema มีขนาดใหญ่ขึ้น

คิวรี Mutation Payload Objects
ทุก mutation ใน schema มีฟิลด์ที่ตรงกันสำหรับคิวรี payload objects ที่เพิ่งสร้างขึ้น โดยมีชื่อว่า {mutationName}MutationPayloadObjects
ฟิลด์เหล่านี้ได้แก่
addCommentToCustomPostMutationPayloadObjects(สำหรับaddCommentToCustomPost)createCustomPostMutationPayloadObjects(สำหรับcreateCustomPost)createMediaItemMutationPayloadObjects(สำหรับcreateMediaItem)createPageMutationPayloadObjects(สำหรับcreatePage)createPostMutationPayloadObjects(สำหรับcreatePost)removeFeaturedImageFromCustomPostMutationPayloadObjects(สำหรับremoveFeaturedImageFromCustomPost)replyCommentMutationPayloadObjects(สำหรับreplyComment)setCategoriesOnPostMutationPayloadObjects(สำหรับsetCategoriesOnPost)setFeaturedImageOnCustomPostMutationPayloadObjects(สำหรับsetFeaturedImageOnCustomPost)setTagsOnPostMutationPayloadObjects(สำหรับsetTagsOnPost)updateCustomPostMutationPayloadObjects(สำหรับupdateCustomPost)updatePageMutationPayloadObjects(สำหรับupdatePage)updatePostMutationPayloadObjects(สำหรับupdatePost)
ฟิลด์เหล่านี้ช่วยให้เราสามารถดึงผลลัพธ์ของ mutations ที่ดำเนินการโดยใช้ @applyField ขณะวนซ้ำรายการในอาร์เรย์
ตัวอย่างเช่น คิวรีต่อไปนี้ทำการ duplicate โพสต์จำนวนมาก
query GetPostsAndExportData
{
postsToDuplicate: posts {
title
rawContent
excerpt
# Already create (and export) the inputs for the mutation
postInput: _echo(value: {
title: $__title
contentAs: {
html: $__rawContent
},
excerpt: $__excerpt
})
@export(as: "postInput", type: LIST)
@remove
}
}
mutation CreatePosts
@depends(on: "GetPostsAndExportData")
{
createdPostMutationPayloadObjectIDs: _echo(value: $postInput)
@underEachArrayItem(
passValueOnwardsAs: "input"
)
@applyField(
name: "createPost"
arguments: {
input: $input
},
setResultInResponse: true
)
@export(as: "createdPostMutationPayloadObjectIDs")
}
query DuplicatePosts
@depends(on: "CreatePosts")
{
createdPostMutationObjectPayloads: createPostMutationPayloadObjects(input: {
ids: $createdPostMutationPayloadObjectIDs
}) {
status
errors {
__typename
...on ErrorPayload {
message
}
}
post {
id
title
rawContent
excerpt
}
}
}โดยค่าเริ่มต้น ฟิลด์เหล่านี้จะไม่ถูกเพิ่มใน GraphQL schema เพื่อเพิ่มฟิลด์เหล่านี้ เราต้องเลือกตัวเลือก "Use payload types for mutations, and add fields to query those payload objects"
เอนทิตีที่ถูก Mutate
Mutation จะคืนค่าเอนทิตีที่ถูก mutate โดยตรงหากสำเร็จ หรือ null หากล้มเหลว และข้อความแสดงข้อผิดพลาดจะแสดงในรายการ errors ระดับบนสุดของ JSON response
ตัวอย่างเช่น mutation updatePost จะคืนค่าออบเจ็กต์ประเภท Post
mutation UpdatePost {
updatePost(input: {
id: 1724,
title: "New title",
status: publish
}) {
id
title
status
}
}หากการดำเนินการสำเร็จ เราจะได้รับ
{
"data": {
"updatePost": {
"id": 1724,
"title": "Some title",
"status": "publish"
}
}
}ในกรณีที่เกิดข้อผิดพลาด ข้อผิดพลาดเหล่านั้นจะปรากฏใน errors entry ของ response ตัวอย่างเช่น หากผู้ใช้ไม่ได้เข้าสู่ระบบ เราจะได้รับ
{
"errors": [
{
"message": "You must be logged in to create or update custom posts'",
"locations": [
{
"line": 2,
"column": 3
}
]
}
],
"data": {
"updatePost": null
}
}เราต้องสังเกตว่า ในผลลัพธ์นี้ errors entry ระดับบนสุดจะมีไม่เพียงแต่ข้อผิดพลาดทางไวยากรณ์ การตรวจสอบ schema และข้อผิดพลาดเชิงตรรกะ (เช่น ไม่ระบุชื่อ argument ของฟิลด์ ร้องขอฟิลด์ที่ไม่มีอยู่ หรือเรียก _sendHTTPRequest ขณะที่เครือข่ายล่ม) แต่ยังรวมถึงข้อผิดพลาดด้าน "content validation" ด้วย (เช่น "คุณไม่มีสิทธิ์แก้ไขโพสต์นี้")
เนื่องจากไม่มีการเพิ่มประเภทพิเศษใดๆ GraphQL schema จะดูกระชับยิ่งขึ้น

การจัดการประเภท Payload Object สำหรับ Mutations
มาดูวิธีจัดการตัวเลือกแรก คือประเภท payload object กัน
Mutations ใน schema คืนค่า payload object บางอย่าง ซึ่งให้ข้อมูลข้อผิดพลาดที่เกิดจาก mutation หรือออบเจ็กต์ที่แก้ไขแล้วหากสำเร็จ (คุณสมบัติทั้ง 2 นี้มักจะ exclusive กัน: errors หรือ object อย่างใดอย่างหนึ่งจะมีค่า และอีกอย่างจะเป็น null)
ข้อผิดพลาดถูกให้ผ่านประเภท "ErrorPayloadUnion" ที่มีข้อผิดพลาดที่เป็นไปได้ทั้งหมดสำหรับ mutation นั้น ข้อผิดพลาดที่เป็นไปได้แต่ละรายการเป็นประเภท "ErrorPayload" บางประเภทที่ implements interface ErrorPayload
ตัวอย่างเช่น operation updatePost คืนค่า PostUpdateMutationPayload ซึ่งมีฟิลด์ต่อไปนี้
status: บ่งบอกว่า operation สำเร็จหรือไม่ โดยมีค่าSUCCESSหรือFAILUREpostและpostID: ออบเจ็กต์โพสต์ที่อัปเดตและ ID ของมัน หากการอัปเดตสำเร็จerrors: รายการของCustomPostUpdateMutationErrorPayloadUnionหากการอัปเดตล้มเหลว
ประเภท union CustomPostUpdateMutationErrorPayloadUnion มีรายการข้อผิดพลาดที่เป็นไปได้ทั้งหมดที่อาจเกิดขึ้นเมื่อแก้ไข custom post
CustomPostDoesNotExistErrorPayloadGenericErrorPayloadLoggedInUserHasNoEditingCustomPostCapabilityErrorPayloadLoggedInUserHasNoPermissionToEditCustomPostErrorPayloadLoggedInUserHasNoPublishingCustomPostCapabilityErrorPayloadUserIsNotLoggedInErrorPayload
ประเภทข้อผิดพลาด GenericErrorPayload อยู่ในประเภท "ErrorPayloadUnion" ทั้งหมด ใช้เมื่อไม่สามารถระบุสาเหตุที่แน่ชัดของข้อผิดพลาดได้ เช่น เมื่อ wp_update_post สร้าง WP_Error เพียงอย่างเดียว ประเภทนี้มีฟิลด์เพิ่มเติม 2 ฟิลด์คือ code และ data
จากนั้น เพื่อดำเนินการ updatePost mutation เราสามารถรัน
mutation UpdatePost(
$postId: ID!
$title: String!
) {
updatePost(
input: {
id: $postId,
title: $title,
}
) {
status
errors {
__typename
...on ErrorPayload {
message
}
...on GenericErrorPayload {
code
}
}
post {
id
title
}
}
}หากการดำเนินการสำเร็จ เราจะได้รับ
{
"data": {
"updatePost": {
"status": "SUCCESS",
"errors": null,
"post": {
"id": 1724,
"title": "This incredible title"
}
}
}
}หากผู้ใช้ไม่ได้เข้าสู่ระบบ เราจะได้รับ
{
"data": {
"updatePost": {
"status": "FAILURE",
"errors": [
{
"__typename": "UserIsNotLoggedInErrorPayload",
"message": "You must be logged in to create or update custom posts"
}
],
"post": null
}
}
}หากผู้ใช้ไม่มีสิทธิ์ในการแก้ไขโพสต์ เราจะได้รับ
{
"data": {
"updatePost": {
"status": "FAILURE",
"errors": [
{
"__typename": "LoggedInUserHasNoEditingCustomPostCapabilityErrorPayload",
"message": "Your user doesn't have permission for editing custom posts."
}
],
"post": null
}
}
}