Tutorial dello schema
Tutorial dello schemaLezione 5: Personalizzare il contenuto per diversi utenti

Lezione 5: Personalizzare il contenuto per diversi utenti

Possiamo recuperare una risposta diversa in un campo in base a un dato interrogato, come i ruoli dell'utente connesso.

Query GraphQL per personalizzare il contenuto per diversi utenti

Questa query GraphQL recupera il contenuto di un articolo e aggiunge un link "Modifica questo articolo" in fondo al contenuto solo per l'utente amministratore:

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
}

Per gli utenti amministratori, la risposta sarà:

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

Per gli utenti non amministratori, la risposta sarà:

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

Lasciare che il server GraphQL (considerando tutte le possibili condizioni) calcoli dinamicamente il valore richiesto per un campo:

  • Semplifica la logica dell'applicazione, poiché esiste un'unica fonte di verità, il codice diventa DRY e i client non devono più implementare la logica corrispondente
  • Rende l'applicazione più affidabile, specialmente quando più client accedono ai dati dal server, poiché implementazioni diverse della stessa logica possono non essere identiche, portando potenzialmente a bug (ancor più quando i client si basano su tecnologie diverse, come JavaScript per un sito web, Java per un'app Android, Swift per un'app iPhone e altri)

Passo dopo passo: creazione della query GraphQL

Di seguito è riportata l'analisi dettagliata del funzionamento della query.

Verificare se l'utente è un amministratore

Questa query verifica se l'utente connesso ha il ruolo "administrator" ed esporta questa condizione nella variabile dinamica $isAdminUser:

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

Esecuzione condizionale delle operazioni

Quando l'Esecuzione di multiple query è abilitata, le direttive @include e @skip possono essere applicate anche alle operazioni. In questo modo, possiamo eseguire o meno un'operazione in base al valore di una variabile dinamica.

Nella query seguente, solo una delle due operazioni verrà eseguita:

  • RetrieveContentForAdminUser viene eseguita solo quando $isAdminUser è true
  • RetrieveContentForNonAdminUser viene eseguita solo quando $isAdminUser è false
query RetrieveContentForAdminUser
  @depends(on: "ExportConditionalVariables")
  @include(if: $isAdminUser)
{
  # ...
}
 
query RetrieveContentForNonAdminUser
  @depends(on: "ExportConditionalVariables")
  @skip(if: $isAdminUser)
{
  # ...
}

Forniamo due risposte diverse per il campo content dell'articolo in base al fatto che l'utente sia amministratore o meno:

  • La prima operazione usa content come alias e calcola il valore del campo dinamicamente, combinando i campi originalContent e wpAdminEditURL tramite _sprintf
  • La seconda operazione recupera il campo content direttamente
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
  }
}

Aggiungere l'operazione da eseguire

Ora abbiamo due operazioni che possono essere eseguite, tuttavia possiamo fornire un solo ?operationName=... durante l'esecuzione della query.

Quindi, aggiungiamo l'operazione ExecuteAll che dipende sia da RetrieveContentForAdminUser che da RetrieveContentForNonAdminUser, contenente il semplice campo id (perché dobbiamo interrogare qualcosa nell'operazione):

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

La chiamata all'endpoint con ?operationName=ExecuteAll caricherà ora entrambe le operazioni, tuttavia solo una di esse verrà effettivamente eseguita.

Rimuovere i dati non necessari

Il passaggio finale consiste nel rimuovere tramite @remove tutti i campi che sono ausiliari (e che quindi non è necessario stampare nella risposta).

La query GraphQL consolidata è:

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
}