Samouczek schematu
Samouczek schematuLekcja 5: Dostosowywanie treści dla różnych użytkowników

Lekcja 5: Dostosowywanie treści dla różnych użytkowników

Możemy pobierać różną odpowiedź w polu w zależności od pewnych danych zapytania, takich jak role zalogowanego użytkownika.

Query GraphQL do dostosowywania treści dla różnych użytkowników

To query GraphQL pobiera treść wpisu, dodając link „Edytuj ten wpis" na końcu treści tylko dla użytkownika administratora:

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
}

Dla użytkowników administratorów odpowiedź będzie wyglądać następująco:

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

Dla użytkowników niebędących administratorami odpowiedź będzie wyglądać następująco:

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

Zlecenie serwerowi GraphQL (biorąc pod uwagę wszystkie możliwe warunki) dynamicznego obliczania wymaganej wartości dla pola:

  • Upraszcza logikę aplikacji, ponieważ istnieje jedno źródło prawdy, kod staje się DRY, a klienty nie muszą już implementować odpowiedniej logiki
  • Sprawia, że aplikacja jest bardziej niezawodna, szczególnie gdy wielu klientów uzyskuje dostęp do danych z serwera, gdyż różne implementacje tej samej logiki mogą nie być identyczne, co może prowadzić do błędów (tym bardziej gdy klienty opierają się na różnych technologiach, takich jak JavaScript dla witryny internetowej, Java dla aplikacji Android, Swift dla aplikacji iPhone i inne)

Krok po kroku: tworzenie query GraphQL

Poniżej znajduje się szczegółowa analiza działania query.

Sprawdzanie, czy użytkownik jest administratorem

To query sprawdza, czy zalogowany użytkownik posiada rolę "administrator", i eksportuje ten warunek do dynamicznej zmiennej $isAdminUser:

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

Warunkowe wykonywanie operacji

Gdy włączone jest Wykonywanie Wielu Queries, dyrektywy @include i @skip mogą być również stosowane do operacji. W ten sposób możemy wykonać lub pominąć operację w zależności od wartości pewnej zmiennej dynamicznej.

W poniższym query tylko jedna z dwóch operacji zostanie wykonana:

  • RetrieveContentForAdminUser jest wykonywana tylko wtedy, gdy $isAdminUser ma wartość true
  • RetrieveContentForNonAdminUser jest wykonywana tylko wtedy, gdy $isAdminUser ma wartość false
query RetrieveContentForAdminUser
  @depends(on: "ExportConditionalVariables")
  @include(if: $isAdminUser)
{
  # ...
}
 
query RetrieveContentForNonAdminUser
  @depends(on: "ExportConditionalVariables")
  @skip(if: $isAdminUser)
{
  # ...
}

Podajmy dwie różne odpowiedzi dla pola content wpisu w zależności od tego, czy użytkownik jest administratorem:

  • Pierwsza operacja używa content jako aliasu i oblicza wartość pola dynamicznie, łącząc pola originalContent i wpAdminEditURL za pomocą _sprintf
  • Druga operacja pobiera pole content bezpośrednio
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
  }
}

Dodawanie operacji do wykonania

Mamy teraz dwie operacje, które mogą zostać wykonane, jednak możemy podać tylko jeden parametr ?operationName=... podczas wykonywania query.

Dlatego dodajemy operację ExecuteAll, która zależy zarówno od RetrieveContentForAdminUser, jak i RetrieveContentForNonAdminUser, zawierającą proste pole id (ponieważ musimy o coś zapytać w operacji):

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

Wywołanie endpointu z parametrem ?operationName=ExecuteAll załaduje obie operacje, jednak tylko jedna z nich zostanie faktycznie wykonana.

Usuwanie niepotrzebnych danych

Ostatnim krokiem jest usunięcie wszystkich pól pomocniczych (których wyniku nie potrzebujemy w odpowiedzi) za pomocą @remove.

Skonsolidowane query GraphQL wygląda następująco:

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
}