对象类型(ObjectType)

使用方式

<?php
namespace app\http\graph;

use \smilecc\think\Support\Types;
use \smilecc\think\Support\ObjectType;

class QueryType extends ObjectType
{
    public function attrs()
    {
        return [
            'name' => 'GraphQueryType',
            'desc' => 'think-graphql的演示类型'
        ];
    }

    public function fields()
    {
        return [
            'hello_world' => Types::user(),
            'user' => [
                'type' => Types::user(),
                'args' => [
                    'id' => Types::nonNull(Types::id())
                ]
            ]
        ];
    }

    public function resolveHelloWorld($val, $args)
    {
        return 'hello world!!!';
    }

    public function resolveUser($val, $args)
    {
        return [
            'id' => $args['id'],
            'nickname' => 'TestUser',
            'created_time' => '2018-07-31 17:21:50'
        ];
    }
}

  • attrs 定义了该Type的名称及描述。
  • fields 定义了该Type的返回字段。

此例中我们定义了一个名叫hello_world的字段,那么只需要定义一个resolveHelloWorld方法为他设置一个值。

我们可以看出字段中使用下划线或小驼峰的情况,我们在resolve时可以直接使用大驼峰来处理它。

例如hello_world->resolveHelloWorldcraeted_time->resolveCreatedTime

在使用我们的自定义Type的时候,我们只需要返回一个数组既可。

public function resolveUser($val, $args)
{
    return [
        'id' => $args['id'],
        'nickname' => 'TestUser',
        'created_time' => '2018-07-31 17:21:50'
    ];
}

在自定义Type的内部,如果我们在外层返回数组中的字段名和自定义Type内部fields中设置的相同,那么无需任何操作,think-graphql会自动帮你返回该值。

如果和内部定义的不一致或需要二次处理,那么我们在自定义Type的内部则需要resolve该字段自己处理一下。

class UserType extends ObjectType
{
    public function attrs()
    {
        return [
            'name' => 'UserType',
            'desc' => '用户类型'
        ];
    }

    public function fields()
    {
        return [
            'id' => Types::id(),
            'nickname' => Types::string(),
            'created_time' => Types::string()
        ];
    }

    public function resolveCreatedTime($val)
    {
        return strtotime($val['created_time']);
    }
}

在这个例子中我们就把上层传递过来的数据 $val 中的 created_time 转换成时间戳再返回。

可重写的方法

方法名 返回类型 说明
attrs array 用于类型属性
fields array 用于该类型的字段
fieldsMap array 用于设置字段重指向数据源中的字段
resolveField any 由实例自己处理所有field的数据返回

attrs(): array

定义当前类型的属性

public function attrs()
{
    return [
        'name' => 'ExampleType',
        'desc' => '演示类型'
    ];
}
字段名 说明
name 必需的 当前类型的名称
desc 当前类型的描述

fields(): array

定义当前类型的返回字段

public function fields()
{
    return [
        'simple' => Types::string(),
        'custom' => [
            'name' => 'CustomField',
            'type' => Types::string(),
            'desc' => '自定义字段',
            'args' => [
                'id' => Types::id(),
                'example' => [
                    'name' => 'ExampleArgField',
                    'type' => Types::string(),
                    'desc' => '实例参数字段',
                    'defaultValue' => '默认值'
                ]
            ]
        ]
    ];
}

以下是当字段类型为一个数组时,可选的数组成员:

字段名 说明
type 必需的 字段的类型
name 字段的名称
desc 描述
args 参数列表
deprecationReason 标识这个字段已经废弃的原因,当不为空时,GraphQL的内省方法不再返回该字段,但是仍然能使用该字段查询

args字段

字段名 说明
type 必需的 参数的类型
name 参数的名称
desc 描述
defaultValue 默认值

fieldsMap(): array

通过重写这个方法,你可以改变 fields 中某个字段在数据源中的指向。

例如 fields 中存在一个叫 title 的字段,但是它在数据源中的实际字段名叫 article_title,那么我们只需要使用如下代码就可以将其指向到它的实际数据源。

public function fieldsMap()
{
    return [
        'title' => 'article_title'
    ];
}

resolveField($value, $args, $context, $info): any

注意 当您重写了这个方法的时候,think-graphql的自动调用 resolve字段名 和自动从 $value 中返回数据的功能将失效,而将使用您定义的 resolveField 方法的返回值。

所以您可以重写这个函数来自定义字段 resolve 机制,以下这个例子是在无 resolve字段名 方法时返回默认值 []

public function resolveField($val, $args, $context, \GraphQL\Type\Definition\ResolveInfo $info)
{
    $methodName = "resolve" . str_replace('_', '', $info->fieldName);
    if (method_exists($this, $methodName)) {
        return $this->{$methodName}($val, $args, $context, $info);
    } else {
        return [];
    }
}