Schema
Schema 定义
Schema 是你类型层次结构的容器,它接受构造函数中的根类型并向内部 GrahpQL 工具提供接收你的类型信息的方法。
在 graphql-php 中,Schema 是 GraphQL\Type\Schema
的一个实例,它的构造函数接受数组形式的配置:
<?php
use GraphQL\Type\Schema;
$schema = new Schema([
'query' => $queryType,
'mutation' => $mutationType,
]);
参见 下面 可用的构造函数选项。
Query 和 Mutation 类型
GraphQL Schema 包含两种基础类型:
- Query 类型是 API 读取的呈现
- Mutation 类型 (可选的) 通过在应用中声明所有可能的变更来公开编写API。
Query 和 Mutation 类型 对象类型 是 API 中包含的常规基础字段:
<?php
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
$queryType = new ObjectType([
'name' => 'Query',
'fields' => [
'hello' => [
'type' => Type::string(),
'resolve' => function() {
return 'Hello World!';
}
],
'hero' => [
'type' => $characterInterface,
'args' => [
'episode' => [
'type' => $episodeEnum
]
],
'resolve' => function ($rootValue, $args) {
return StarWarsData::getHero(isset($args['episode']) ? $args['episode'] : null);
},
]
]
]);
$mutationType = new ObjectType([
'name' => 'Mutation',
'fields' => [
'createReview' => [
'type' => $createReviewOutput,
'args' => [
'episode' => $episodeEnum,
'review' => $reviewInputObject
],
'resolve' => function($val, $args) {
// 计划描述
}
]
]
]);
请记住,除了声明 API 覆盖范围的特殊含义之外,那些类型与其他类型 对象类型 是相同的,并且他们的字段作用也是完全相同的。
Mutation 类型也只是常规对象类型, 区别主要是在语义上。
Mutation 类型字段的名称通常是动词,并且他们几乎总是带有参数,时常是比较复杂的输入值 (详阅 变更和输入类型)。
配置选项
GraphQL Schema 构造函数需要 GraphQL\Type\SchemaConfig
的实例或
包含以下选项的数组:
Option | Type | Notes |
---|---|---|
query | ObjectType |
必须。 读取 API 中包含根级字段的对象类型 (通常命名为 "Query") |
mutation | ObjectType |
写入 API 中包含根级字段的对象类型 (通常命名为 "Mutation") |
subscription | ObjectType |
保留用于将来的描述实现。目前表现为 graphql-js 自检查询的兼容,用于各种客户端 (如 Relay 或 GraphiQL) |
directives | Directive[] |
schema 支持的完整 指令 列表。 默认包含内建指令 @skip 和 @include 。 如果你传递自定义指令并且依然想使用内建指令,请声明添加它们。例如: array_merge(GraphQL::getStandardDirectives(), [$myCustomDirective]); |
types | ObjectType[] |
对象类型类表,它在静态 schema 解析期间是不能被 graphql-php 发现的。 大多数情况下,对象类型未曾在字段中被直接引用,但它依然是 schema 的一部分时会用到,因为它实现了一个在 resolveType 中调用解析为此对象类型的接口。 请注意,您在此处无需传递所有类型 ,它只是具体用例的解决方法。 |
typeLoader | callable |
function($name) 返回给定的类型实例名称。 多次调用情况下,必须返回同样的实例。 查阅下文延迟类型加载部分。 |
使用配置类
如果你更喜欢在 IDE 中使用自动完成和静态时间验证的流式接口进行配置,使用 GraphQL\Type\SchemaConfig
来替代数组形式:
<?php
use GraphQL\Type\SchemaConfig;
use GraphQL\Type\Schema;
$config = SchemaConfig::create()
->setQuery($myQueryType)
->setTypeLoader($myTypeLoader);
$schema = new Schema($config);
懒加载类型
默认情况下, Schema 会扫描你的所有类型,字段和参数提供给 GraphQL 的查询. 当 Schema 有许多类型时,他可能会导致性能上的开销.
这种情况下,建议通过 typeLoader(懒加载) 选项传递给 schema 构造器 并将所有的 fields(字段) 定义为回调.
类型加载的概念与PHP类加载非常相似,但是请记住 typeLoader(类型加载) 必须始终返回类型相同的实例.
使用例子:
<?php
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Schema;
class Types
{
private $types = [];
public function get($name)
{
if (!isset($this->types[$name])) {
$this->types[$name] = $this->{$name}();
}
return $this->types[$name];
}
private function MyTypeA()
{
return new ObjectType([
'name' => 'MyTypeA',
'fields' => function() {
return [
'b' => ['type' => $this->get('MyTypeB')]
];
}
]);
}
private function MyTypeB()
{
// ...
}
}
$registry = new Types();
$schema = new Schema([
'query' => $registry->get('Query'),
'typeLoader' => function($name) use ($registry) {
return $registry->get($name);
}
]);
Schema 的验证
默认情况下, Schema 是在类型和字段简单验证下定义创建的
(因为验证需要完整的schema扫描并且在大的schema下,代价会变的非常大)。
但是有一个特殊的方法 assertValid() 在schema实例中抛出 GraphQL\Error\InvariantViolation
当遇到任何异常错误时, 比如:
- 类型/参数的使用无效
- 缺少接口的实现
- 接口的实现无效
- 其他schema的错误...
Schema 验证应该在 CLI 命令或者在编译你的项目中使用.
绝对不要在生产环境中调用 web 请求。
使用例子:
<?php
try {
$schema = new GraphQL\Type\Schema([
'query' => $myQueryType
]);
$schema->assertValid();
} catch (GraphQL\Error\InvariantViolation $e) {
echo $e->getMessage();
}
本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。