Projekt dyrektyw
Dyrektywy odgrywają ważną rolę: pozwalają implementować funkcje, które nie są natywnie obsługiwane przez specyfikację GraphQL ani przez sam serwer GraphQL. Dyrektywy mogą w ten sposób wypełnić lukę funkcjonalną, aby API mogło spełniać swoje wymagania — zarówno te znane, jak i nieznane.
Z tego powodu dyrektywy są niezwykle ważnym elementem w fundamentach serwera GraphQL. Gato GraphQL opiera się na solidnym i przemyślanym projekcie architektonicznym dla dyrektyw, który sprawia, że jest zarówno rozszerzalny, jak i potężny.
Funkcjonalność niskopoziomowa
Jako decyzja projektowa, silnik zależy bezpośrednio od potoku dyrektyw przy rozwiązywaniu queries. Z tego powodu dyrektywy są traktowane jako komponenty niskopoziomowe, z dostępem do obiektu, w którym przechowywana jest odpowiedź.
W rezultacie każda niestandardowa dyrektywa ma możliwość modyfikowania odpowiedzi GraphQL.
Oczywistym przypadkiem użycia jest dyrektywa @remove, która pozwala wskazać w queries, czy wolimy pominąć odpowiedź pola zamiast otrzymywać wartość null (istnieje zgłoszenie w specyfikacji dotyczące tej funkcji).
Efektywne wywołania dyrektyw
Dyrektywy otrzymują wszystkie swoje obiekty i pola, których dotyczą, razem, w ramach jednego wykonania.
Na przykład wywołanie API Google Translate powinno odbywać się jak najrzadziej. W tej queries jest wywoływane tylko raz, zawierając 10 fragmentów tekstu do przetłumaczenia (2 pola, title i excerpt, dla 5 postów):
query {
posts(pagination:{ limit: 5 }) {
title
excerpt
titleES: title @translate(from: "en", to: "es")
excerptES: excerpt @translate(from: "en", to: "es")
}
}W tej queries są 3 wywołania do API, jedno dla każdego języka (hiszpański, francuski i niemiecki), po 10 ciągów znaków, wszystkie wywołania są współbieżne:
query {
posts(pagination:{ limit: 5 }) {
title
excerpt
titleES: title @translate(from: "en", to: "es")
excerptES: excerpt @translate(from: "en", to: "es")
titleDE: title @translate(from: "en", to: "de")
excerptDE: excerpt @translate(from: "en", to: "de")
titleFR: title @translate(from: "en", to: "fr")
excerptFR: excerpt @translate(from: "en", to: "fr")
}
}Sygnatura funkcji
To jest interfejs dyrektywy pola. Zwróć uwagę na parametry, które funkcja resolveDirective otrzymuje:
public function resolveDirective(
RelationalTypeResolverInterface $relationalTypeResolver,
array $idFieldSet,
FieldDataAccessProviderInterface $fieldDataAccessProvider,
array $succeedingPipelineFieldDirectiveResolvers,
array $idObjects,
array $unionTypeOutputKeyIDs,
array $previouslyResolvedIDFieldValues,
array &$succeedingPipelineIDFieldSet,
array &$succeedingPipelineFieldDataAccessProviders,
array &$resolvedIDFieldValues,
array &$messages,
EngineIterationFeedbackStore $engineIterationFeedbackStore,
): void;Te parametry dowodzą niskopoziomowej natury dyrektywy:
$idFieldSet: lista identyfikatorów per pole do przetworzenia przez dyrektywę$succeedingPipelineIDFieldSet: lista identyfikatorów per pole do przetworzenia przez dyrektywy na późniejszym etapie potoku$resolvedIDFieldValues: obiekt odpowiedzi
Pozostałe parametry umożliwiają: dostęp do zmiennych queries i definiowanie zmiennych dynamicznych, przekazywanie wiadomości z niestandardowymi danymi między dyrektywami, zgłaszanie błędów i ostrzeżeń, identyfikowanie i wyświetlanie przestarzałości oraz przechowywanie metryk.