Şema eğitimi
Şema eğitimiDers 5: Farklı kullanıcılara göre içerik özelleştirme

Ders 5: Farklı kullanıcılara göre içerik özelleştirme

Sorgulanan verinin bir parçasına, örneğin oturum açmış kullanıcının rollerine bağlı olarak bir alanda farklı yanıt alabiliriz.

Farklı kullanıcılara göre içerik özelleştirmek için GraphQL query

Bu GraphQL query, gönderi içeriğini alır ve yalnızca yönetici kullanıcı için içeriğin en altına bir "Bu gönderiyi düzenle" bağlantısı ekler:

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
}

Yönetici kullanıcılar için yanıt şu şekilde olacaktır:

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

Yönetici olmayan kullanıcılar için yanıt şu şekilde olacaktır:

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

GraphQL sunucusunun (tüm olası koşullar göz önüne alınarak) bir alan için gereken değeri dinamik olarak hesaplaması:

  • Uygulamanın mantığını basitleştirir; tek bir doğruluk kaynağı bulunur, kod DRY hale gelir ve istemcilerin artık ilgili mantığı uygulaması gerekmez
  • Uygulamayı daha güvenilir kılar; özellikle sunucudan veri alan birden fazla istemci olduğunda, aynı mantığın farklı uygulamaları özdeş olmayabilir ve potansiyel olarak hatalara yol açabilir (farklı teknolojilere dayanan istemcilerde — web sitesi için JavaScript, Android uygulaması için Java, iPhone uygulaması için Swift ve diğerleri — bu durum çok daha belirgin hale gelir)

Adım adım: GraphQL query oluşturma

Aşağıda query'nin nasıl çalıştığına dair ayrıntılı analiz yer almaktadır.

Kullanıcının yönetici olup olmadığını öğrenmek

Bu query, oturum açmış kullanıcının "administrator" rolüne sahip olup olmadığını kontrol eder ve bu koşulu $isAdminUser dinamik değişkeni olarak dışa aktarır:

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

İşlemlerin koşullu olarak çalıştırılması

Çoklu Query Çalıştırma etkinleştirildiğinde, @include ve @skip direktifleri işlemlere de uygulanabilir. Bu sayede bir işlemi, dinamik bir değişkenin değerine bağlı olarak çalıştırıp çalıştırmamayı belirleyebiliriz.

Aşağıdaki query'de iki işlemden yalnızca biri çalıştırılacaktır:

  • RetrieveContentForAdminUser yalnızca $isAdminUser true olduğunda çalıştırılır
  • RetrieveContentForNonAdminUser yalnızca $isAdminUser false olduğunda çalıştırılır
query RetrieveContentForAdminUser
  @depends(on: "ExportConditionalVariables")
  @include(if: $isAdminUser)
{
  # ...
}
 
query RetrieveContentForNonAdminUser
  @depends(on: "ExportConditionalVariables")
  @skip(if: $isAdminUser)
{
  # ...
}

Kullanıcının yönetici olup olmadığına bağlı olarak gönderinin content alanı için iki farklı yanıt sağlayalım:

  • İlk işlem content'i takma ad olarak kullanır ve alanın değerini dinamik olarak hesaplar; originalContent ile wpAdminEditURL alanlarını _sprintf aracılığıyla birleştirir
  • İkinci işlem content alanını doğrudan alır
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
  }
}

Çalıştırılacak işlemi eklemek

Artık çalıştırılabilecek iki işlemimiz var; ancak query'yi çalıştırırken yalnızca bir ?operationName=... sağlayabiliriz.

Bu nedenle, hem RetrieveContentForAdminUser hem de RetrieveContentForNonAdminUser'a bağlı olan ve basit id alanını içeren (çünkü işlemde bir şey sorgulamak zorundayız) ExecuteAll işlemini ekliyoruz:

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

Endpoint'i ?operationName=ExecuteAll ile çağırmak artık her iki işlemi de yükleyecek; ancak yalnızca biri gerçekten çalıştırılacaktır.

Gereksiz verileri kaldırmak

Son adım, yardımcı niteliğindeki (dolayısıyla yanıtta çıktılarını yazdırmamız gerekmeyen) tüm alanları @remove aracılığıyla kaldırmaktır.

Birleştirilmiş GraphQL query şu şekildedir:

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
}