Architectuur
ArchitectuurOntwerp van directives

Ontwerp van directives

Directives spelen een belangrijke rol: ze maken het mogelijk om functies te implementeren die niet van nature worden ondersteund door de GraphQL-specificatie of door de GraphQL-server zelf. Directives kunnen zo de functionele leemte opvullen, zodat de API aan haar vereisten kan voldoen — zowel bekende als onbekende.

Om die reden zijn directives een uiterst belangrijk element in de fundamenten van de GraphQL-server. Gato GraphQL steunt op een solide en doordacht architectuurontwerp voor directives, waardoor het zowel uitbreidbaar als krachtig wordt.

Laagniveau-functionaliteit

Als ontwerpbeslissing is de engine rechtstreeks afhankelijk van de directive-pipeline voor het oplossen van queries. Om die reden worden directives behandeld als laagniveau-componenten, met toegang tot het object waarin het antwoord wordt opgeslagen.

Als gevolg hiervan heeft elke aangepaste directive de mogelijkheid om het GraphQL-antwoord te wijzigen.

Een voor de hand liggend gebruiksscenario is de @remove-directive, waarmee je in de queries kunt aangeven of je de respons van een veld liever weglaat dan een null-waarde te ontvangen (er is een melding in de specificatie over deze functie).

Efficiënte directive-aanroepen

Directives ontvangen al hun betrokken objecten en velden samen, in één enkele uitvoering.

Zo moet het aanroepen van de Google Translate API zo weinig mogelijk keren gebeuren. In deze query wordt het slechts één keer aangeroepen, met 10 tekststukken om te vertalen (2 velden, title en excerpt, voor 5 posts):

query {
  posts(pagination:{ limit: 5 }) {
    title
    excerpt
    titleES: title @translate(from: "en", to: "es")
    excerptES: excerpt @translate(from: "en", to: "es")
  }
}

In deze query zijn er 3 aanroepen naar de API, één voor elke taal (Spaans, Frans en Duits), elk 10 tekenreeksen, alle aanroepen zijn gelijktijdig:

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

Functie-signatuur

Dit is de interface voor field directives. Let op de parameters die de functie resolveDirective ontvangt:

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;

Deze parameters tonen het laagniveau-karakter van de directive aan:

  • $idFieldSet: de lijst van ID's per veld die door de directive moeten worden verwerkt
  • $succeedingPipelineIDFieldSet: de lijst van ID's per veld die door directives in een latere fase van de pipeline moeten worden verwerkt
  • $resolvedIDFieldValues: het antwoordobject

De overige parameters maken het mogelijk om: toegang te krijgen tot de queries-variabelen en dynamische variabelen te definiëren, berichten met aangepaste gegevens tussen directives door te sturen, fouten en waarschuwingen te melden, verouderde elementen te identificeren en weer te geven, en statistieken op te slaan.