Extension du schéma
Extension du schémaVariables dynamiques

Variables dynamiques

La requête GraphQL suivante reçoit la variable $limit pour savoir combien d'articles récupérer, et le type de la variable, Int, doit être déclaré dans l'opération :

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

C'est le comportement attendu dans GraphQL, dans lequel nous fournissons la valeur de la variable dans un dictionnaire JSON défini dans le même document :

{
  "limit": 3
}

C'est un comportement « statique », partagé par de nombreux langages. En PHP, par exemple, les arguments des fonctions peuvent indiquer leur type, comme dans le code ci-dessous, où l'entrée $number est définie comme un entier :

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

Maintenant, lors de la déclaration d'une variable dans le corps de la fonction PHP, nous n'indiquons pas son type ; le type de la variable est déterminé par le contexte dans lequel elle est utilisée. Dans le code ci-dessous, l'affectation d'une valeur entière à $double fera de cette variable un entier :

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

Grâce aux directives personnalisées, le serveur GraphQL peut fournir un comportement similaire et prendre en charge les variables dynamiques, où une variable dynamique obtient sa valeur lors de la résolution de la requête sur le serveur, au lieu d'être fournie par le client.

L'extension Exécution de Requêtes Multiples de Gato GraphQL est livrée avec la directive personnalisée @export, qui permet d'exporter la valeur d'un champ dans une variable (dynamique), puis nous pouvons lire la valeur de cette variable dans un argument de champ d'une opération différente :

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

La variable $userName est dynamique, et il n'est pas nécessaire de définir son type (String) dans l'opération qui l'utilise (GetPostsContainingString). Le serveur GraphQL comprend déjà le contexte.

Si nous essayons d'utiliser la valeur de la variable avec un type non correspondant, comme dans la requête suivante (où un Int est attendu mais la variable dynamique est un 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
  }
}

...alors le serveur GraphQL échoue lors de la coercition de la valeur, et retourne une erreur :

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

Spécification GraphQL

Cette fonctionnalité ne fait actuellement pas partie de la spécification GraphQL, mais elle a été demandée dans :