Schema-Tutorial
Schema-TutorialLektion 5: Inhalte für verschiedene Benutzer anpassen

Lektion 5: Inhalte für verschiedene Benutzer anpassen

Wir können eine unterschiedliche Antwort in einem Feld basierend auf abgefragten Daten abrufen, wie z. B. den Rollen des angemeldeten Benutzers.

GraphQL-Query zum Anpassen von Inhalten für verschiedene Benutzer

Diese GraphQL-Query ruft den Beitragsinhalt ab und fügt am Ende des Inhalts einen Link „Diesen Beitrag bearbeiten" nur für den Admin-Benutzer hinzu:

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
}

Für Admin-Benutzer lautet die Antwort:

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

Für Nicht-Admin-Benutzer lautet die Antwort:

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

Wenn der GraphQL-Server (angesichts aller möglichen Bedingungen) den erforderlichen Wert für ein Feld dynamisch berechnet:

  • Vereinfacht dies die Logik der Anwendung, da es eine einzige Quelle der Wahrheit gibt, der Code wird DRY und Clients müssen die entsprechende Logik nicht mehr selbst implementieren
  • Macht dies die Anwendung zuverlässiger, besonders wenn mehrere Clients auf Daten vom Server zugreifen, da unterschiedliche Implementierungen derselben Logik nicht identisch sein können und potenziell zu Bugs führen (umso mehr, wenn Clients auf unterschiedlichen Technologien basieren, wie JavaScript für eine Website, Java für eine Android-App, Swift für eine iPhone-App und andere)

Schritt für Schritt: die GraphQL-Query erstellen

Im Folgenden wird detailliert erläutert, wie die Query funktioniert.

Herausfinden, ob der Benutzer ein Admin ist

Diese Query prüft, ob der angemeldete Benutzer die Rolle "administrator" hat, und exportiert diese Bedingung in die dynamische Variable $isAdminUser:

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

Bedingte Ausführung von Operationen

Wenn Multiple Query Execution aktiviert ist, können die Direktiven @include und @skip auch auf Operationen angewendet werden. Auf diese Weise können wir eine Operation je nach dem Wert einer dynamischen Variable ausführen oder nicht.

In der folgenden Query wird nur eine der beiden Operationen ausgeführt:

  • RetrieveContentForAdminUser wird nur ausgeführt, wenn $isAdminUser true ist
  • RetrieveContentForNonAdminUser wird nur ausgeführt, wenn $isAdminUser false ist
query RetrieveContentForAdminUser
  @depends(on: "ExportConditionalVariables")
  @include(if: $isAdminUser)
{
  # ...
}
 
query RetrieveContentForNonAdminUser
  @depends(on: "ExportConditionalVariables")
  @skip(if: $isAdminUser)
{
  # ...
}

Wir geben zwei verschiedene Antworten für das content-Feld des Beitrags zurück, je nachdem ob der Benutzer ein Admin ist oder nicht:

  • Die erste Operation verwendet content als Alias und berechnet den Feldwert dynamisch, indem die Felder originalContent und wpAdminEditURL über _sprintf zusammengeführt werden
  • Die zweite Operation ruft das content-Feld direkt ab
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
  }
}

Die auszuführende Operation hinzufügen

Nun haben wir zwei Operationen, die ausgeführt werden können, aber wir können beim Ausführen der Query nur ein ?operationName=... angeben.

Daher fügen wir die Operation ExecuteAll hinzu, die sowohl von RetrieveContentForAdminUser als auch von RetrieveContentForNonAdminUser abhängt und das einfache Feld id enthält (weil wir in der Operation etwas abfragen müssen):

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

Der Aufruf des Endpunkts mit ?operationName=ExecuteAll lädt nun beide Operationen, aber nur eine davon wird tatsächlich ausgeführt.

Nicht benötigte Daten entfernen

Der letzte Schritt besteht darin, alle Felder, die Hilfszwecken dienen (und deren Ausgabe wir daher nicht in der Antwort benötigen), über @remove zu entfernen.

Die konsolidierte GraphQL-Query lautet:

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
}