Schema 扩充动态变量
动态变量
下面的 GraphQL Query 接收变量 $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 服务器可以提供类似的行为并支持动态变量。动态变量的值在服务器解析 Query 时获取,而不是由客户端提供。
Gato GraphQL 的 Multiple Query Execution 扩展附带了自定义指令 @export,它允许将字段的值导出到(动态)变量中,然后可以在不同操作的字段参数中读取该变量的值:
query ExportLoggedInUserName {
me {
name @export(as: "userName")
}
}
query GetPostsContainingString
@depends(on: "ExportLoggedInUserName")
{
posts(filter: { search: $userName }) {
id
title
}
}变量 $userName 是动态的,无需在使用它的操作(GetPostsContainingString)中定义其类型(String)。GraphQL 服务器已经理解其上下文。
如果尝试使用类型不匹配的变量值,如下面的 Query(期望 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 规范,但已在以下地方被提出: