Rozszerzanie schematu
Rozszerzanie schematuZmienne dynamiczne

Zmienne dynamiczne

Poniższe query GraphQL otrzymuje zmienną $limit, aby wiedzieć, ile postów pobrać, a typ zmiennej, Int, musi być zadeklarowany w operacji:

query GetPosts($limit: Int) {
  posts(limit: $limit) {
    id
    title
  }
}

To jest oczekiwane zachowanie w GraphQL, w którym dostarczamy wartość zmiennej w słowniku JSON zdefiniowanym w tym samym dokumencie:

{
  "limit": 3
}

Jest to zachowanie „statyczne", wspólne dla wielu języków. Na przykład w PHP argumenty funkcji mogą wskazywać swój typ, jak w poniższym kodzie, gdzie wejście $number jest zdefiniowane jako liczba całkowita:

function double(int $number): int
{
  return $number * 2;
}

Teraz, deklarując zmienną wewnątrz ciała funkcji PHP, nie wskazujemy jej typu; typ zmiennej jest określany przez kontekst, w którym zmienna jest używana. W poniższym kodzie przypisanie wartości całkowitej do $double sprawi, że ta zmienna będzie liczbą całkowitą:

function double(int $number): int
{
  // This var is an integer, but we don't need to declare it
  $double = $number * 2;
  return $double;
}

Dzięki niestandardowym dyrektywom serwer GraphQL może zapewnić podobne zachowanie i obsługiwać zmienne dynamiczne, gdzie zmienna dynamiczna uzyskuje swoją wartość podczas rozwiązywania queries na serwerze, zamiast być dostarczaną przez klienta.

Rozszerzenie Wykonywanie wielu queries Gato GraphQL zawiera niestandardową dyrektywę @export, która pozwala eksportować wartość pola do zmiennej (dynamicznej), a następnie możemy odczytać wartość tej zmiennej w argumencie pola z innej operacji:

query ExportLoggedInUserName {
  me {
    name @export(as: "userName")
  }
}
 
query GetPostsContainingString
  @depends(on: "ExportLoggedInUserName")
{
  posts(filter: { search: $userName }) {
    id
    title
  }
}

Zmienna $userName jest dynamiczna i nie ma potrzeby definiowania jej typu (String) w operacji, która jej używa (GetPostsContainingString). Serwer GraphQL już rozumie kontekst.

Jeśli spróbujemy użyć wartości zmiennej z niezgodnym typem, jak w poniższym query (gdzie oczekiwany jest Int, ale zmienna dynamiczna jest String):

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

...wtedy serwer GraphQL nie może przekształcić wartości i zwraca błąd:

{
  "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"
      }
    }
  ]
}

Specyfikacja GraphQL

Ta funkcjonalność nie jest obecnie częścią specyfikacji GraphQL, ale została zgłoszona w: