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&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:
RetrieveContentForAdminUserjest wykonywana tylko wtedy, gdy$isAdminUserma wartośćtrueRetrieveContentForNonAdminUserjest wykonywana tylko wtedy, gdy$isAdminUserma 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
contentjako aliasu i oblicza wartość pola dynamicznie, łącząc polaoriginalContentiwpAdminEditURLza pomocą_sprintf - Druga operacja pobiera pole
contentbezpoś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
}