Dynamische Variablen
Die folgende GraphQL-Query erhält die Variable $limit, um zu wissen, wie viele Beiträge abgerufen werden sollen, und der Typ der Variable, Int, muss in der Operation deklariert werden:
query GetPosts($limit: Int) {
posts(limit: $limit) {
id
title
}
}Dies ist das erwartete Verhalten in GraphQL, bei dem wir den Variablenwert in einem JSON-Wörterbuch angeben, das im selben Dokument definiert ist:
{
"limit": 3
}Dies ist ein „statisches" Verhalten, das viele Sprachen teilen. In PHP beispielsweise können Funktionsargumente ihren Typ angeben, wie im folgenden Code, wo die Eingabe $number als Integer definiert ist:
function double(int $number): int
{
return $number * 2;
}Wenn wir nun eine Variable innerhalb des PHP-Funktionskörpers deklarieren, geben wir ihren Typ nicht an; der Typ der Variable wird durch den Kontext bestimmt, in dem sie verwendet wird. Im folgenden Code macht die Zuweisung eines Integer-Werts zu $double diese Variable zu einem Integer:
function double(int $number): int
{
// This var is an integer, but we don't need to declare it
$double = $number * 2;
return $double;
}Dank benutzerdefinierter Direktiven kann der GraphQL-Server ein ähnliches Verhalten bereitstellen und dynamische Variablen unterstützen, wobei eine dynamische Variable ihren Wert beim Auflösen der Query im Server erhält, anstatt vom Client bereitgestellt zu werden.
Die Erweiterung Multiple Query Execution von Gato GraphQL enthält die benutzerdefinierte Direktive @export, die es ermöglicht, den Wert eines Felds in eine (dynamische) Variable zu exportieren, und dann können wir den Wert dieser Variable in einem Feldargument einer anderen Operation lesen:
query ExportLoggedInUserName {
me {
name @export(as: "userName")
}
}
query GetPostsContainingString
@depends(on: "ExportLoggedInUserName")
{
posts(filter: { search: $userName }) {
id
title
}
}Die Variable $userName ist dynamisch, und es ist nicht notwendig, ihren Typ (String) in der Operation zu definieren, die sie verwendet (GetPostsContainingString). Der GraphQL-Server versteht den Kontext bereits.
Wenn wir versuchen, den Variablenwert mit einem nicht übereinstimmenden Typ zu verwenden, wie in der folgenden Query (wo ein Int erwartet wird, die dynamische Variable aber ein String ist):
query ExportDynamicVariable {
_echo(value: "Hello world!") @export(as: "stringVar") # Exported: String
}
query UseVariable
@depends(on: "ExportDynamicVariable")
{
posts(
pagination: {
limit: $stringVar # Expected: Int, received: String
}
) {
id
}
}...dann schlägt der GraphQL-Server bei der Konvertierung des Werts fehl und gibt einen Fehler zurück:
{
"errors": [
{
"message": "Cannot cast value 'Hello world!' for type 'Int'",
"locations": [
{
"line": 10,
"column": 13
}
],
"extensions": {
"path": [
"{limit: $stringVar}",
"(pagination: {limit: $stringVar})",
"posts(pagination: {limit: $stringVar}) { ... }",
"query UseVariable @depends(on: \"ExportDynamicVariable\") { ... }"
],
"type": "QueryRoot",
"field": "posts(pagination: {limit: $stringVar}) { ... }",
"id": "root",
"code": "gql@5.6.1[16]",
"specifiedBy": "https:\/\/spec.graphql.org\/draft\/#sec-Values-of-Correct-Type"
}
}
]
}GraphQL-Spezifikation
Diese Funktionalität ist derzeit nicht Teil der GraphQL-Spezifikation, wurde aber angefragt in: