Berinteraksi dengan API GraphQL
Berinteraksi dengan API GraphQLMenangani payload mutation

Menangani payload mutation

Field mutation dapat dikonfigurasi untuk mengembalikan salah satu dari 2 tipe entitas yang berbeda:

  • Tipe objek payload
  • Langsung entitas yang dimutasi

Tipe objek payload

Tipe objek payload berisi semua data yang berkaitan dengan mutation:

  • Status mutation (sukses atau gagal)
  • Error (jika ada) menggunakan tipe GraphQL yang berbeda, atau
  • Entitas yang berhasil dimutasi

Misalnya, mutation updatePost mengembalikan objek bertipe PostUpdateMutationPayload, dan kita masih perlu melakukan query pada field post-nya untuk mengambil entitas post yang telah diperbarui:

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
    }
  }
}

Objek payload memungkinkan kita merepresentasikan error dengan lebih baik, bahkan dengan memiliki tipe GraphQL unik untuk setiap jenis error. Ini memungkinkan kita menampilkan respons yang berbeda untuk error yang berbeda dalam aplikasi, sehingga meningkatkan pengalaman pengguna.

Pada contoh di atas, jika operasi berhasil, kita akan menerima:

{
  "data": {
    "updatePost": {
      "status": "SUCCESS",
      "errors": null,
      "post": {
        "id": 1724,
        "title": "Some title",
        "status": "publish"
      }
    }
  }
}

Jika pengguna belum masuk, kita akan menerima:

{
  "data": {
    "updatePost": {
      "status": "FAILURE",
      "errors": [
        {
          "__typename": "UserIsNotLoggedInErrorPayload",
          "message": "You must be logged in to create or update custom posts"
        }
      ],
      "post": null
    }
  }
}

Jika pengguna tidak memiliki izin untuk mengedit post, kita akan menerima:

{
  "data": {
    "updatePost": {
      "status": "FAILURE",
      "errors": [
        {
          "__typename": "LoggedInUserHasNoEditingCustomPostCapabilityErrorPayload",
          "message": "Your user doesn't have permission for editing custom posts."
        }
      ],
      "post": null
    }
  }
}

Dalam mode ini, skema GraphQL akan berisi banyak tipe tambahan MutationPayload, MutationErrorPayloadUnion, dan ErrorPayload, sehingga ukurannya akan lebih besar:

Skema GraphQL dengan tipe objek payload untuk mutation

Query objek payload mutation

Setiap mutation dalam skema memiliki field yang sesuai untuk melakukan query pada objek payload yang baru dibuat, dengan nama {mutationName}MutationPayloadObjects.

Field-field ini meliputi:

  • addCommentToCustomPostMutationPayloadObjects (untuk addCommentToCustomPost)
  • createCustomPostMutationPayloadObjects (untuk createCustomPost)
  • createMediaItemMutationPayloadObjects (untuk createMediaItem)
  • createPageMutationPayloadObjects (untuk createPage)
  • createPostMutationPayloadObjects (untuk createPost)
  • removeFeaturedImageFromCustomPostMutationPayloadObjects (untuk removeFeaturedImageFromCustomPost)
  • replyCommentMutationPayloadObjects (untuk replyComment)
  • setCategoriesOnPostMutationPayloadObjects (untuk setCategoriesOnPost)
  • setFeaturedImageOnCustomPostMutationPayloadObjects (untuk setFeaturedImageOnCustomPost)
  • setTagsOnPostMutationPayloadObjects (untuk setTagsOnPost)
  • updateCustomPostMutationPayloadObjects (untuk updateCustomPost)
  • updatePageMutationPayloadObjects (untuk updatePage)
  • updatePostMutationPayloadObjects (untuk updatePost)

Field-field ini memungkinkan kita mengambil hasil mutation yang dieksekusi menggunakan @applyField saat mengiterasi item dalam sebuah array.

Misalnya, query berikut menduplikasi post secara massal:

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
    }
  }
}

Secara default, field-field ini tidak ditambahkan ke skema GraphQL. Untuk itu, kita harus memilih opsi "Use payload types for mutations, and add fields to query those payload objects".

Entitas yang dimutasi

Mutation akan langsung mengembalikan entitas yang dimutasi jika berhasil, atau null jika gagal, dan pesan error apa pun akan ditampilkan di entri errors tingkat atas pada respons JSON.

Misalnya, mutation updatePost akan mengembalikan objek bertipe Post:

mutation UpdatePost {
  updatePost(input: {
    id: 1724,
    title: "New title",
    status: publish
  }) {
    id
    title
    status
  }
}

Jika operasi berhasil, kita akan menerima:

{
  "data": {
    "updatePost": {
      "id": 1724,
      "title": "Some title",
      "status": "publish"
    }
  }
}

Jika terjadi error, error tersebut akan muncul di bawah entri errors pada respons. Misalnya, jika pengguna belum masuk, kita akan menerima:

{
    "errors": [
      {
        "message": "You must be logged in to create or update custom posts'",
        "locations": [
          {
            "line": 2,
            "column": 3
          }
        ]
      }
  ],
  "data": {
    "updatePost": null
  }
}

Kita perlu memperhatikan bahwa, akibatnya, entri errors tingkat atas akan berisi tidak hanya error sintaksis, validasi skema, dan logika (misalnya: tidak meneruskan nama argumen field, meminta field yang tidak ada, atau memanggil _sendHTTPRequest saat jaringan mati), tetapi juga error "validasi konten" (misalnya: "Anda tidak diizinkan untuk memodifikasi post ini").

Karena tidak ada tipe tambahan yang ditambahkan, skema GraphQL akan terlihat lebih ramping:

Skema GraphQL tanpa tipe objek payload untuk mutation

Menangani tipe objek payload untuk mutation

Mari kita lihat cara menangani opsi pertama, yaitu tipe objek payload.

Mutation dalam skema mengembalikan beberapa objek payload, yang menyediakan error (jika ada) yang dihasilkan dari mutation, atau objek yang dimodifikasi jika berhasil (2 properti ini kemungkinan besar bersifat eksklusif: baik errors atau object yang akan memiliki nilai, dan yang lainnya akan null).

Error disediakan melalui beberapa tipe "ErrorPayloadUnion", yang berisi semua kemungkinan error untuk mutation tersebut. Setiap kemungkinan error adalah beberapa tipe "ErrorPayload" yang mengimplementasikan interface ErrorPayload.

Misalnya, operasi updatePost mengembalikan PostUpdateMutationPayload, yang berisi field-field berikut:

  • status: apakah operasi berhasil atau tidak, dengan nilai SUCCESS atau FAILURE
  • post dan postID: objek post yang diperbarui dan ID-nya, jika pembaruan berhasil
  • errors: daftar CustomPostUpdateMutationErrorPayloadUnion, jika pembaruan gagal.

Tipe union CustomPostUpdateMutationErrorPayloadUnion berisi daftar semua kemungkinan error yang dapat terjadi saat memodifikasi custom post:

  • CustomPostDoesNotExistErrorPayload
  • GenericErrorPayload
  • LoggedInUserHasNoEditingCustomPostCapabilityErrorPayload
  • LoggedInUserHasNoPermissionToEditCustomPostErrorPayload
  • LoggedInUserHasNoPublishingCustomPostCapabilityErrorPayload
  • UserIsNotLoggedInErrorPayload

Tipe error GenericErrorPayload terdapat dalam semua tipe "ErrorPayloadUnion". Tipe ini digunakan setiap kali alasan spesifik untuk error tidak dapat ditunjukkan, seperti ketika wp_update_post hanya menghasilkan WP_Error. Tipe ini menyediakan dua field tambahan: code dan data.

Kemudian, untuk mengeksekusi mutation updatePost, kita dapat menjalankan:

mutation UpdatePost(
  $postId: ID!
  $title: String!
) {
  updatePost(
    input: {
      id: $postId,
      title: $title,
    }
  ) {
    status
    errors {
      __typename
      ...on ErrorPayload {
        message
      }
      ...on GenericErrorPayload {
        code
      }
    }
    post {
      id
      title
    }
  }
}

Jika operasi berhasil, kita akan menerima:

{
  "data": {
    "updatePost": {
      "status": "SUCCESS",
      "errors": null,
      "post": {
        "id": 1724,
        "title": "This incredible title"
      }
    }
  }
}

Jika pengguna belum masuk, kita akan menerima:

{
  "data": {
    "updatePost": {
      "status": "FAILURE",
      "errors": [
        {
          "__typename": "UserIsNotLoggedInErrorPayload",
          "message": "You must be logged in to create or update custom posts"
        }
      ],
      "post": null
    }
  }
}

Jika pengguna tidak memiliki izin untuk mengedit post, kita akan menerima:

{
  "data": {
    "updatePost": {
      "status": "FAILURE",
      "errors": [
        {
          "__typename": "LoggedInUserHasNoEditingCustomPostCapabilityErrorPayload",
          "message": "Your user doesn't have permission for editing custom posts."
        }
      ],
      "post": null
    }
  }
}