Interfaces
定义接口类型
接口是一种抽象类型,它包含一类必须包含的用于实现接口的一组字段。
在 graphql-php 接口类型中是一个 GraphQL\Type\Definition\InterfaceType
(或其中一个子类)的实例,它接受构造函数中的配置数组:
<?php
use GraphQL\Type\Definition\InterfaceType;
use GraphQL\Type\Definition\Type;
$character = new InterfaceType([
'name' => 'Character',
'description' => 'A character in the Star Wars Trilogy',
'fields' => [
'id' => [
'type' => Type::nonNull(Type::string()),
'description' => 'The id of the character.',
],
'name' => [
'type' => Type::string(),
'description' => 'The name of the character.'
]
],
'resolveType' => function ($value) {
if ($value->type === 'human') {
return MyTypes::human();
} else {
return MyTypes::droid();
}
}
]);
本示例使用 内联 样式来定义接口,但你也可以使用 继承或类型语言。
配置选项
InterfaceType 的构造函数接受一个数组。以下是允许的选项的完整列表:
选项 | 类型 | 说明 |
---|---|---|
name | string |
必需。 Schema 中该接口类型的唯一名称 |
fields | array |
必需。 接口实现者需要定义的字段列表。与 对象类型的字段 相同 |
description | string |
用于客户端的此类型的明文描述(例如,GraphiQL 用于自动生成的文档) |
resolveType | callback |
function($value, $context, ResolveInfo $info) 从父字段的解析器接收 $value,并返回 $value 的具体接口实现者。 |
实现 interface
要实现该接口,只需将其添加到对象类型定义的 接口 数组中即可:
<?php
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\ObjectType;
$humanType = new ObjectType([
'name' => 'Human',
'fields' => [
'id' => [
'type' => Type::nonNull(Type::string()),
'description' => 'The id of the character.',
],
'name' => [
'type' => Type::string(),
'description' => 'The name of the character.'
]
],
'interfaces' => [
$character
]
]);
请注意,对象类型必须包含完全相同类型(包括 非空 指定)和参数的所有接口字段。
唯一的例外是对象的字段类型比接口中定义的该字段的类型更具体(请参阅下面的 接口字段的Covariant返回类型 )。
接口字段的协变返回类型
实现接口的对象类型可能会将字段类型更改得更具体。
例如:
interface A {
field1: A
}
type B implements A {
field1: B
}
共享接口字段
因为每个实现了接口的对象类型必须都具有相同的字段集合,所以复用对象类型中的接口字段定义合情合理。
<?php
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\ObjectType;
$humanType = new ObjectType([
'name' => 'Human',
'interfaces' => [
$character
],
'fields' => [
'height' => Type::float(),
$character->getField('id'),
$character->getField('name')
]
]);
在这个例子中,字段定义只被创建了一次(作为一个接口类型),接下来就可以被所有的接口实现者复用。它可以节省几微秒和数千字节,同时确保接口和实现者的字段定义始终一致。
但是这也带来了字段解析问题。有两种方案可以解决这个问题:
-
如果字段解析算法在所有的接口实现者中都是一样的 - 可以简单添加
resolve 选项到接口本身的字段定义中。 -
如果字段解析在各个实现中各不相同- 可以在 对象类型配置 中定义 resolveField 选项,然后在那里处理字段解析(注意:resolve 选项在对象类型定义中的优先级高于 resolveField 选项)。
数据获取中的接口角色
数据获取过程中的接口唯一职责就是返回 resolveType 中给定的 $value 的具体对象类型。然后将字段解析委派给此对象类型的解析器来处理。
如果 resolveType 选项被省略,graphql-php 将遍历所有的接口实现者然后使用它们的 isTypeOf 回调方法来选择第一个最适合的。 因此这明显比单独调用 resolveType 低效。所以建议尽量定义 resolveType 。
本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。