Progettazione delle direttive
Le direttive svolgono un ruolo importante: permettono di implementare le funzionalità che non sono supportate nativamente dalla specifica GraphQL o dal server GraphQL stesso. Le direttive possono così colmare questo vuoto funzionale, affinché l'API possa soddisfare i propri requisiti, siano essi noti o sconosciuti.
Per questo motivo, le direttive sono un elemento estremamente importante nelle fondamenta del server GraphQL. Gato GraphQL si basa su una progettazione architetturale solida e robusta per le direttive, il che gli consente di essere al contempo estensibile e potente.
Funzionalità di basso livello
Come decisione di progettazione, il motore dipende direttamente dalla pipeline delle direttive per risolvere la query. Per questo motivo, le direttive sono trattate come componenti di basso livello, con accesso all'oggetto in cui viene memorizzata la risposta.
Di conseguenza, qualsiasi direttiva personalizzata ha la capacità di modificare la risposta GraphQL.
Un caso d'uso evidente è la direttiva @remove, che permette di indicare nella query se si preferisce omettere la risposta di un campo anziché ricevere un valore null (esiste una issue nella specifica riguardo a questa funzionalità ).
Chiamate efficienti alle direttive
Le direttive ricevono tutti i loro oggetti e campi interessati insieme, in una singola esecuzione.
Ad esempio, la chiamata all'API Google Translate dovrebbe essere effettuata il minor numero di volte possibile. In questa query, viene chiamata una sola volta, contenente 10 frammenti di testo da tradurre (2 campi, title ed excerpt, per 5 post):
query {
posts(pagination:{ limit: 5 }) {
title
excerpt
titleES: title @translate(from: "en", to: "es")
excerptES: excerpt @translate(from: "en", to: "es")
}
}In questa query ci sono 3 chiamate all'API, una per ogni lingua (spagnolo, francese e tedesco), 10 stringhe ciascuna, tutte le chiamate sono concorrenti:
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")
}
}Firma della funzione
Ecco l'interfaccia di direttiva di campo. Si notino i parametri che la funzione resolveDirective riceve:
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;Questi parametri evidenziano la natura di basso livello della direttiva:
$idFieldSet: l'elenco degli ID per campo da elaborare da parte della direttiva$succeedingPipelineIDFieldSet: l'elenco degli ID per campo da elaborare da parte delle direttive in una fase successiva della pipeline$resolvedIDFieldValues: l'oggetto di risposta
Gli altri parametri consentono di: accedere alle variabili della query e definire variabili dinamiche, trasmettere messaggi con dati personalizzati tra le direttive, generare errori e avvisi, identificare e visualizzare le deprecazioni, e memorizzare metriche.