Schema-tutorial
Schema-tutorialLes 5: Inhoud aanpassen voor verschillende gebruikers

Les 5: Inhoud aanpassen voor verschillende gebruikers

We kunnen een andere respons ophalen in een veld afhankelijk van bepaalde gegevens in de query, zoals de rollen van de ingelogde gebruiker.

GraphQL-query om inhoud aan te passen voor verschillende gebruikers

Deze GraphQL-query haalt de berichtinhoud op en voegt een link "Bewerk dit bericht" toe onderaan de inhoud, maar alleen voor de beheerder:

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
}

Voor beheerders zal de respons er als volgt uitzien:

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

Voor niet-beheerders zal de respons er als volgt uitzien:

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

De GraphQL-server laten (rekening houdend met alle mogelijke condities) de vereiste waarde voor een veld dynamisch berekenen:

  • Vereenvoudigt de logica van de applicatie, omdat er één bron van waarheid is, de code DRY wordt en clients de bijbehorende logica niet meer zelf hoeven te implementeren
  • Maakt de applicatie betrouwbaarder, met name wanneer meerdere clients gegevens van de server opvragen, omdat verschillende implementaties van dezelfde logica niet identiek kunnen zijn, wat mogelijk tot bugs leidt (des te meer wanneer clients op verschillende technologieën zijn gebaseerd, zoals JavaScript voor een website, Java voor een Android-app, Swift voor een iPhone-app, en andere)

Stap voor stap: de GraphQL-query opbouwen

Hieronder volgt een gedetailleerde analyse van hoe de query werkt.

Controleren of de gebruiker een beheerder is

Deze query controleert of de ingelogde gebruiker de rol "administrator" heeft, en exporteert deze conditie naar de dynamische variabele $isAdminUser:

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

Conditionele uitvoering van operaties

Wanneer Meervoudige Query-uitvoering is ingeschakeld, kunnen de directives @include en @skip ook worden toegepast op operaties. Op die manier kunnen we een operatie al dan niet uitvoeren afhankelijk van de waarde van een dynamische variabele.

In de onderstaande query wordt slechts één van de twee operaties uitgevoerd:

  • RetrieveContentForAdminUser wordt alleen uitgevoerd wanneer $isAdminUser true is
  • RetrieveContentForNonAdminUser wordt alleen uitgevoerd wanneer $isAdminUser false is
query RetrieveContentForAdminUser
  @depends(on: "ExportConditionalVariables")
  @include(if: $isAdminUser)
{
  # ...
}
 
query RetrieveContentForNonAdminUser
  @depends(on: "ExportConditionalVariables")
  @skip(if: $isAdminUser)
{
  # ...
}

Laten we twee verschillende responsen geven voor het veld content van het bericht, afhankelijk van of de gebruiker een beheerder is of niet:

  • De eerste operatie gebruikt content als alias en berekent de waarde van het veld dynamisch door de velden originalContent en wpAdminEditURL samen te voegen via _sprintf
  • De tweede operatie haalt het veld content rechtstreeks op
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
  }
}

De uit te voeren operatie toevoegen

We hebben nu twee operaties die mogelijk worden uitgevoerd, maar we kunnen slechts één ?operationName=... opgeven bij het uitvoeren van de query.

Daarom voegen we de operatie ExecuteAll toe die afhankelijk is van zowel RetrieveContentForAdminUser als RetrieveContentForNonAdminUser, en die het eenvoudige veld id bevat (omdat we iets moeten opvragen in de operatie):

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

Door het eindpunt aan te roepen met ?operationName=ExecuteAll worden beide operaties geladen, maar slechts één ervan wordt daadwerkelijk uitgevoerd.

Overbodige gegevens verwijderen

De laatste stap is het verwijderen van alle hulpvelden (waarvan we de uitvoer niet in de respons nodig hebben) via @remove.

De geconsolideerde GraphQL-query is:

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
}