Laravel API 系列教程(四):基于 GraphQL 构建 Laravel API —— 基本使用篇


GraphQL 简介

GraphQL 是一个用于 API 的查询语言,同时也是一个通过为你的数据定义类型系统进行查询的服务端运行时。GraphQL 与数据库或任意存储引擎无关,仅仅是代码逻辑层面的查询实现。

通过 GraphQL,可以提高 API 调用的灵活性。我们可以在访问 API 时像编写数据库查询一样通过编写查询语句指定需要的数据,这在构建复杂 API 时很有用,GraphQL 已经提供了用户接口帮助来我们编写查询,此外,还提供了编写查询时自动提示的 UI 工具 —— GraphiQL,这些接口和工具可以极大提高查询编写效率。

GraphQL 与其说是一种语言,不如说是一种接口规范和风格,类似 REST,都是运行在业务逻辑层之上:

更多关于 GraphQL 的信息,请参考官方文档(英文吃力的同学可以看中文版)。

安装配置

GraphQL 为各大语言提供了 SDK,今天,我们的主题是基于 GraphQL 在 Laravel 中构建 API,需要通过相应的扩展包来实现。

我们还是在前面的 API 系列教程(系列一系列二系列三)基础之上进行开发,首先通过 Composer 安装扩展包:

composer require folklore/graphql

由于基于 Laravel 5.5 版本,所以无需手动注册服务提供者,接下来发布配置文件到 config 目录:

php artisan vendor:publish --provider="Folklore\GraphQL\ServiceProvider"

下面我们将以 User 模型为例简单演示下查询和更新操作 API 的构建。

创建 Query

GraphQL 基于类型进行操作,所以开始之前需要为 User 模型创建一个 UserType

php artisan make:graphql:type UserType

生成的文件位于 app/GraphQL/Type 目录下,编写 UserType 类代码如下:

namespace App\GraphQL\Type;

use GraphQL\Type\Definition\Type;
use Folklore\GraphQL\Support\Type as BaseType;
use GraphQL;

class UserType extends BaseType
{
    protected $attributes = [
        'name' => 'User',
        'description' => 'A User'
    ];

    public function fields()
    {
        return [
            'id' => [
                'type' => Type::nonNull(Type::string()),
                'description' => 'The id of the user'
            ],
            'email' => [
                'type' => Type::string(),
                'description' => 'The email of the user'
            ]
        ];
    }

    protected function resolveEmailField($root, $args)
    {
        return strtolower($root->email);
    }
}

然后在 config/graphql.php 中注册该类型:

'types' => [
    'User' => \App\GraphQL\Type\UserType::class,
],

或者在服务提供者如 AppServiceProviderboot 方法中新增下面这段代码,效果和在配置文件新增配置一样:

GraphQL::addType('App\GraphQL\Type\UserType', 'User');

定义好 UserType 之后,我们来编写查询实现,首先通过以下 Artisan 命令创建查询类:

php artisan make:graphql:query UserQuery

生成的文件位于 app/GraphQL/Query 目录下,编写 UserQuery 类代码如下:

namespace App\GraphQL\Query;

use App\User;
use Folklore\GraphQL\Support\Query;
use GraphQL\Type\Definition\Type;
use GraphQL;

class UserQuery extends Query
{
    protected $attributes = [
        'name' => 'users',
    ];

    public function type()
    {
        return Type::listOf(GraphQL::type('User'));
    }

    public function args()
    {
        return [
            'id' => ['name' => 'id', 'type' => Type::string()],
            'email' => ['name' => 'email', 'type' => Type::string()]
        ];
    }

    public function resolve($root, $args)
    {
        if (isset($args['id'])) {
            return User::where('id', $args['id'])->get();
        } elseif (isset($args['email'])) {
            return User::where('email', $args['email'])->get();
        } else {
            return User::all();
        }
    }
}

然后配置 config/graphql.php 新增查询结构:

'schemas' => [
    'default' => [
        'query' => [
            'users' => \App\GraphQL\Query\UserQuery::class,
        ],
        'mutation' => [

        ]
    ]
],

现在我们就可以通过接口访问用户数据了。可以通过 Postman 进行测试:

也可以通过 Chrome 浏览器扩展工具 GraphiQL 来测试(推荐使用这种方式):

创建 Mutation

一个简单的类比就是 Query 对应数据库的查询操作,Mutation 则对应数据库的变更操作。我们可以通过以下命令快速创建一个 Mutation 类:

php artisan make:graphql:mutation UpdateUserPasswordMutation

编辑新生成的 UpdateUserPasswordMutation 类:

namespace App\GraphQL\Mutation;

use App\User;
use Folklore\GraphQL\Support\Mutation;
use GraphQL\Type\Definition\Type;
use GraphQL;

class UpdateUserPasswordMutation extends Mutation
{
    protected $attributes = [
        'name' => 'updateUserPassword',
    ];

    public function type()
    {
        return GraphQL::type('User');
    }

    public function args()
    {
        return [
            'id' => ['name' => 'id', 'type' => Type::nonNull(Type::string())],
            'password' => ['name' => 'password', 'type' => Type::nonNull(Type::string())]
        ];
    }

    public function resolve($root, $args)
    {
        $user = User::find($args['id']);

        if (!$user) {
            return null;
        }

        $user->password = bcrypt($args['password']);
        $user->save();

        return $user;
    }
}

接下来配置 config/graphql.php 新增变更操作:

'schemas' => [
    'default' => [
        'query' => [
            'users' => \App\GraphQL\Query\UserQuery::class,
        ],
        'mutation' => [
            'updateUserPassword' => \App\GraphQL\Mutation\UpdateUserPasswordMutation::class,
        ]
    ]
],

然后就可以在 GraphiQL 中进行变更密码测试了:

变更时进行字段验证

以更新用户邮箱为例,首先创建变更类:

 php artisan make:graphql:mutation UpdateUserEmailMutation

然后编辑新生成的 UpdateUserEmailMutation 类:

namespace App\GraphQL\Mutation;

use App\User;
use Folklore\GraphQL\Support\Mutation;
use GraphQL\Type\Definition\Type;
use GraphQL;

class UpdateUserEmailMutation extends Mutation
{
    protected $attributes = [
        'name' => 'updateUserEmailMutation',
    ];

    public function type()
    {
        return GraphQL::type('User');
    }

    public function args()
    {
        return [
            'id' => ['name' => 'id', 'type' => Type::nonNull(Type::string())],
            'email' => ['name' => 'email', 'type' => Type::nonNull(Type::string())]
        ];
    }

    public function rules()
    {
        return [
            'id' => 'required',
            'email' => ['required', 'email']
        ];
    }

    public function resolve($root, $args)
    {
        $user = User::find($args['id']);

        if (!$user) {
            return null;
        }

        $user->email = $args['email'];
        $user->save();

        return $user;
    }
}

在配置文件 config/graphql.php 中新增变更配置:

'schemas' => [
    'default' => [
        'query' => [
            'users' => \App\GraphQL\Query\UserQuery::class,
        ],
        'mutation' => [
            'updateUserPassword' => \App\GraphQL\Mutation\UpdateUserPasswordMutation::class,
            'updateUserEmail' => \App\GraphQL\Mutation\UpdateUserEmailMutation::class,
        ]
    ]
],

最后在 GraphiQL 中进行变更邮箱测试,如果邮箱格式不正确的话会报错:

以上我们基于 GraphQL 实现了简单的模型查询和变更 API,并且实现了对变更字段的验证,这些都是最基本的应用示例,下一篇我们继续深入探讨基于 GraphQL 构建 Laravel API,包括参数查询、关联查询、自定义字段/接口、枚举以及接口认证等。


点赞 取消点赞 收藏 取消收藏

<< 上一篇: Laravel API 系列教程(三):使用 API Resource 来创建自己的 {JSON:API} 格式 API

>> 下一篇: Laravel API 系列教程(五):基于 GraphQL 构建 Laravel API —— 高级使用篇