Tutorial skema
Tutorial skemaPelajaran 5: Menyesuaikan konten untuk pengguna berbeda

Pelajaran 5: Menyesuaikan konten untuk pengguna berbeda

Kita dapat mengambil respons berbeda pada sebuah field tergantung pada sebagian data yang di-query, seperti peran pengguna yang sedang login.

Query GraphQL untuk menyesuaikan konten bagi pengguna berbeda

Query GraphQL ini mengambil konten posting, menambahkan tautan "Edit posting ini" di bagian bawah konten hanya untuk pengguna admin:

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
}

Untuk pengguna admin, responsnya akan berupa:

{
  "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&amp;action=edit\">(Admin only) Edit post<\/a><\/p>"
    }
  }
}

Untuk pengguna non-admin, responsnya akan berupa:

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

Membiarkan server GraphQL (dengan mempertimbangkan semua kemungkinan kondisi) menghitung secara dinamis nilai yang diperlukan untuk sebuah field:

  • Menyederhanakan logika aplikasi, karena ada satu sumber kebenaran tunggal, kode menjadi DRY, dan klien tidak perlu lagi mengimplementasikan logika yang bersangkutan
  • Membuat aplikasi lebih andal, terutama ketika beberapa klien mengakses data dari server, karena implementasi yang berbeda dari logika yang sama bisa tidak identik, yang berpotensi menyebabkan bug (lebih lagi ketika klien berbasis teknologi yang berbeda, seperti JavaScript untuk website, Java untuk aplikasi Android, Swift untuk aplikasi iPhone, dan lainnya)

Langkah demi langkah: membuat query GraphQL

Berikut adalah analisis terperinci tentang cara kerja query tersebut.

Mengetahui apakah pengguna adalah admin

Query ini memeriksa apakah pengguna yang sedang login memiliki peran "administrator", dan mengekspor kondisi ini ke dalam variabel dinamis $isAdminUser:

query
{
  me {
    roleNames
    isAdminUser: _inArray(
        value: "administrator",
        array: $__roleNames
    )
      @export(as: "isAdminUser")
  }
}

Eksekusi kondisional operasi

Ketika Multiple Query Execution diaktifkan, direktif @include dan @skip juga dapat diterapkan pada operasi. Dengan cara ini, kita dapat mengeksekusi atau tidak suatu operasi tergantung pada nilai dari suatu variabel dinamis.

Dalam query di bawah ini, hanya satu dari dua operasi yang akan dieksekusi:

  • RetrieveContentForAdminUser dieksekusi hanya ketika $isAdminUser bernilai true
  • RetrieveContentForNonAdminUser dieksekusi hanya ketika $isAdminUser bernilai false
query RetrieveContentForAdminUser
  @depends(on: "ExportConditionalVariables")
  @include(if: $isAdminUser)
{
  # ...
}
 
query RetrieveContentForNonAdminUser
  @depends(on: "ExportConditionalVariables")
  @skip(if: $isAdminUser)
{
  # ...
}

Mari kita berikan dua respons berbeda untuk field content posting tergantung pada apakah pengguna adalah admin atau bukan:

  • Operasi pertama menggunakan content sebagai alias, dan menghitung nilai field secara dinamis, menggabungkan field originalContent dan wpAdminEditURL melalui _sprintf
  • Operasi kedua mengambil field content secara langsung
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
  }
}

Menambahkan operasi yang akan dieksekusi

Sekarang kita memiliki dua operasi yang mungkin dieksekusi, namun kita hanya dapat memberikan satu ?operationName=... saat mengeksekusi query.

Maka, kita tambahkan operasi ExecuteAll yang bergantung pada RetrieveContentForAdminUser dan RetrieveContentForNonAdminUser, yang berisi field sederhana id (karena kita harus meng-query sesuatu dalam operasi):

query ExecuteAll
  @depends(on: [
    "RetrieveContentForAdminUser",
    "RetrieveContentForNonAdminUser"
  ])
{
  id
}

Memanggil endpoint dengan ?operationName=ExecuteAll sekarang akan memuat kedua operasi, namun hanya satu di antaranya yang akan benar-benar dieksekusi.

Menghapus data yang tidak diperlukan

Langkah terakhir adalah menghapus semua field yang bersifat tambahan (dan karenanya tidak perlu dicetak outputnya dalam respons) melalui @remove.

Query GraphQL yang sudah terkonsolidasi adalah:

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
}