Tutoriel du schéma
Tutoriel du schémaLeçon 5 : Personnaliser le contenu pour différents utilisateurs

Leçon 5 : Personnaliser le contenu pour différents utilisateurs

Nous pouvons récupérer une réponse différente dans un champ en fonction d'une donnée interrogée, telle que les rôles de l'utilisateur connecté.

Requête GraphQL pour personnaliser le contenu pour différents utilisateurs

Cette requête GraphQL récupère le contenu d'un article et ajoute un lien « Modifier cet article » en bas du contenu uniquement pour l'utilisateur administrateur :

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
}

Pour les utilisateurs administrateurs, la réponse sera :

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

Pour les utilisateurs non administrateurs, la réponse sera :

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

Laisser le serveur GraphQL (compte tenu de toutes les conditions possibles) calculer dynamiquement la valeur requise pour un champ :

  • Simplifie la logique de l'application, car il n'y a qu'une seule source de vérité, le code devient DRY, et les clients n'ont plus besoin d'implémenter la logique correspondante
  • Rend l'application plus fiable, surtout lorsque plusieurs clients accèdent aux données du serveur, car différentes implémentations d'une même logique peuvent ne pas être identiques, entraînant potentiellement des bugs (d'autant plus lorsque les clients reposent sur des technologies différentes, comme JavaScript pour un site web, Java pour une application Android, Swift pour une application iPhone, etc.)

Étape par étape : création de la requête GraphQL

Voici l'analyse détaillée du fonctionnement de la requête.

Déterminer si l'utilisateur est un administrateur

Cette requête vérifie si l'utilisateur connecté possède le rôle "administrator", et exporte cette condition dans la variable dynamique $isAdminUser :

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

Exécution conditionnelle des opérations

Lorsque l'Exécution de multiples requêtes est activée, les directives @include et @skip peuvent également être appliquées aux opérations. Ainsi, nous pouvons exécuter ou non une opération en fonction de la valeur d'une variable dynamique.

Dans la requête ci-dessous, une seule des deux opérations sera exécutée :

  • RetrieveContentForAdminUser est exécutée uniquement lorsque $isAdminUser est true
  • RetrieveContentForNonAdminUser est exécutée uniquement lorsque $isAdminUser est false
query RetrieveContentForAdminUser
  @depends(on: "ExportConditionalVariables")
  @include(if: $isAdminUser)
{
  # ...
}
 
query RetrieveContentForNonAdminUser
  @depends(on: "ExportConditionalVariables")
  @skip(if: $isAdminUser)
{
  # ...
}

Fournissons deux réponses différentes pour le champ content de l'article selon que l'utilisateur est administrateur ou non :

  • La première opération utilise content comme alias, et calcule la valeur du champ dynamiquement, en combinant les champs originalContent et wpAdminEditURL via _sprintf
  • La seconde opération récupère le champ content directement
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
  }
}

Ajouter l'opération à exécuter

Nous avons maintenant deux opérations qui peuvent être exécutées, mais nous ne pouvons fournir qu'un seul ?operationName=... lors de l'exécution de la requête.

Nous ajoutons donc l'opération ExecuteAll qui dépend de RetrieveContentForAdminUser et de RetrieveContentForNonAdminUser, contenant le simple champ id (car nous devons interroger quelque chose dans l'opération) :

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

L'appel du point de terminaison avec ?operationName=ExecuteAll chargera désormais les deux opérations, mais une seule d'entre elles sera réellement exécutée.

Supprimer les données inutiles

La dernière étape consiste à supprimer via @remove tous les champs qui sont auxiliaires (et que nous n'avons donc pas besoin d'afficher dans la réponse).

La requête GraphQL consolidée est :

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
}