Динамические переменные
Приведённый ниже GraphQL-запрос принимает переменную $limit, чтобы узнать, сколько записей нужно получить, и тип переменной — Int — должен быть объявлен в операции:
query GetPosts($limit: Int) {
posts(limit: $limit) {
id
title
}
}Это ожидаемое поведение в GraphQL, при котором мы указываем значение переменной в JSON-словаре, определённом в том же документе:
{
"limit": 3
}Это «статическое» поведение, характерное для многих языков программирования. В PHP, например, аргументы функций могут указывать свой тип — как в приведённом ниже коде, где входной параметр $number определён как целое число:
function double(int $number): int
{
return $number * 2;
}Когда же переменная объявляется внутри тела PHP-функции, её тип не указывается — он определяется контекстом использования. В коде ниже присвоение целочисленного значения переменной $double делает её целым числом:
function double(int $number): int
{
// This var is an integer, but we don't need to declare it
$double = $number * 2;
return $double;
}Благодаря пользовательским директивам сервер GraphQL может обеспечить аналогичное поведение и поддерживать динамические переменные, где динамическая переменная получает своё значение при разрешении запроса на сервере, а не предоставляется клиентом.
Расширение Multiple Query Execution для Gato GraphQL поставляется с пользовательской директивой @export, которая позволяет экспортировать значение поля в (динамическую) переменную, после чего можно считать это значение из аргумента поля в другой операции:
query ExportLoggedInUserName {
me {
name @export(as: "userName")
}
}
query GetPostsContainingString
@depends(on: "ExportLoggedInUserName")
{
posts(filter: { search: $userName }) {
id
title
}
}Переменная $userName является динамической, и нет необходимости определять её тип (String) в операции, которая её использует (GetPostsContainingString). Сервер GraphQL уже понимает контекст.
Если попытаться использовать значение переменной с несовместимым типом — как в следующем запросе (где ожидается Int, но динамическая переменная имеет тип 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
}
}...то сервер GraphQL завершится ошибкой при приведении значения и вернёт ошибку:
{
"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
Данная функциональность в настоящее время не является частью спецификации GraphQL, однако была запрошена в: