热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

[译+]LaravelGraphQLReadMe文档

原文地址:readme.mdadvanced.md使用语法Schemas从1.0版本开始,可以定义多个语法,如果您想要一个公共的入口,另一个需要身份验证的入口,那么拥有多个语法是非

原文地址:

  • readme.md
  • advanced.md

使用

语法 / Schemas

从 1.0 版本开始, 可以定义多个语法, 如果您想要一个公共的入口,另一个需要身份验证的入口,那么拥有多个语法是非常有用的。

您可以在配置中定义多个语法:

'schema' => 'default',
'schemas' => [
'default' => [
'query' => [
//'users' => 'App\GraphQL\Query\UsersQuery'
],
'mutation' => [
//'updateUserEmail' => 'App\GraphQL\Query\UpdateUserEmailMutation'
]
],
'secret' => [
'query' => [
//'users' => 'App\GraphQL\Query\UsersQuery'
],
'mutation' => [
//'updateUserEmail' => 'App\GraphQL\Query\UpdateUserEmailMutation'
]
]
]

或者可以使用 facade 来添加语法

GraphQL::addSchema('secret', [
'query' => [
'users' => 'App\GraphQL\Query\UsersQuery'
],
'mutation' => [
'updateUserEmail' => 'App\GraphQL\Query\UpdateUserEmailMutation'
]
]);

随后, 你可以使用 facade 来创建语法

// Will return the default schema defined by 'schema' in the config
$schema = GraphQL::schema();
// Will return the 'secret' schema
$schema = GraphQL::schema('secret');
// Will build a new schema
$schema = GraphQL::schema([
'query' => [
//'users' => 'App\GraphQL\Query\UsersQuery'
],
'mutation' => [
//'updateUserEmail' => 'App\GraphQL\Query\UpdateUserEmailMutation'
]
]);

你可以通过指定的语法来访问

// Default schema
http://homestead.app/graphql?query=query+FetchUsers{users{id,email}}
// Secret schema
http://homestead.app/graphql/secret?query=query+FetchUsers{users{id,email}}

创建查询

首先你需要创建一个类型

namespace App\GraphQL\Type;
use GraphQL\Type\Definition\Type;
use Folklore\GraphQL\Support\Type as GraphQLType;
class UserType extends GraphQLType
{
protected $attributes = [
'name' => 'User',
'description' => 'A user'
];
/*
* Uncomment following line to make the type input object.
* http://graphql.org/learn/schema/#input-types
*/
// protected $inputObject = true;
public function fields()
{
return [
'id' => [
'type' => Type::nonNull(Type::string()),
'description' => 'The id of the user'
],
'email' => [
'type' => Type::string(),
'description' => 'The email of user'
]
];
}
// If you want to resolve the field yourself, you can declare a method
// with the following format resolve[FIELD_NAME]Field()
protected function resolveEmailField($root, $args)
{
return strtolower($root->email);
}
}

然后将类型添加到 config/graphql.php 文件中

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

你也可以使用 GraphQL Facade 来进行添加, 添加到 service provider 中

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

然后, 你需要定义一个查询并且返回这个类型(或者列表). 你同样也可以在指定的参数, 这些参数可以用在 resolve 方法中.

namespace App\GraphQL\Query;
use GraphQL;
use GraphQL\Type\Definition\Type;
use Folklore\GraphQL\Support\Query;
use App\User;
class UsersQuery 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();
} else if(isset($args['email'])) {
return User::where('email', $args['email'])->get();
} else {
return User::all();
}
}
}

添加 query 到 config/graphql.php 文件中

'schemas' => [
'default' => [
'query' => [
'users' => 'App\GraphQL\Query\UsersQuery'
],
// ...
]
]

这样就OK了, 你可以使用 /graphql 来进行查询了. 尝试使用 get 请求来获取下数据

query FetchUsers {
users {
id
email
}
}

或者使用 url 地址来进行请求

http://homestead.app/graphql?query=query+FetchUsers{users{id,email}}

创建修改

更改就是另外一种形式的查询, 他接受参数(用来进行更改或者创建使用的)并且返回一个对象或者指定的类型

例如使用修改来更新用户的密码, 首先你需要定义 mutation

namespace App\GraphQL\Mutation;
use GraphQL;
use GraphQL\Type\Definition\Type;
use Folklore\GraphQL\Support\Mutation;
use App\User;
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;
}
}

就想 resolve 方法. 你使用参数来更新你的模型并且返回她.

然后添加 mutation 到 config/graphql.php 文件中

'schema' => [
'default' => [
'mutation' => [
'updateUserPassword' => 'App\GraphQL\Mutation\UpdateUserPasswordMutation'
],
// ...
]
]

你可以使用如下的查询来进行修改

mutation users {
updateUserPassword(id: "1", password: "newpassword") {
id
email
}
}

url 中可以如下请求

http://homestead.app/graphql?query=mutation+users{updateUserPassword(id: "1", password: "newpassword"){id,email}}

添加修改验证

在修改中增加验证是可以的. 老铁. 它使用 laravel Validator 来处理验证并且返回相应的参数.

当创建 mutation 的时候, 你可以添加如下方法来定义验证规则:

namespace App\GraphQL\Mutation;
use GraphQL;
use GraphQL\Type\Definition\Type;
use Folklore\GraphQL\Support\Mutation;
use App\User;
class UpdateUserEmailMutation extends Mutation
{
protected $attributes = [
'name' => 'UpdateUserEmail'
];
public function type()
{
return GraphQL::type('User');
}
public function args()
{
return [
'id' => ['name' => 'id', 'type' => Type::string()],
'email' => ['name' => 'email', 'type' => 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;
}
}

同样, 你可以在参数中定义规则:

class UpdateUserEmailMutation extends Mutation
{
//...
public function args()
{
return [
'id' => [
'name' => 'id',
'type' => Type::string(),
'rules' => ['required']
],
'email' => [
'name' => 'email',
'type' => Type::string(),
'rules' => ['required', 'email']
]
];
}
//...
}

当你执行修改的时候, 会返回验证错误. 由于 GraphQL 规范定义了错误的格式,因此会将验证错误消息作为额外的 validation 属性添加到错误对象中。为了找到验证错误,应该检查一个 message 等于 validation 的时候,然后 validation 属性将包含 Laravel Validator 返回的正常错误消息信息.

{
"data": {
"updateUserEmail": null
},
"errors": [
{
"message": "validation",
"locations": [
{
"line": 1,
"column": 20
}
],
"validation": {
"email": [
"The email is invalid."
]
}
}
]
}

高级用法

查询变量

GraphQL 允许你使用变量来查询数据, 从而不用在查询中硬编码值. 如下

query FetchUserByID($id: String) {
user(id: $id) {
id
email
}
}

当你查询 GraphQL 的时候可以传递 variables 参数

http://homestead.app/graphql?query=query+FetchUserByID($id:String){user(id:$id){id,email}}&variables={"id":"1"}

查询嵌入资源

如果想查询嵌入资源

query FetchUser{
user(id: 123456789) {
id
posts(id: 987654321) {
id
}
}
}

你需要在 UserType 中添加 post 字段并且实现 resolveField 方法

public function fields()
{
return [
'id' => [
'type' => Type::nonNull(Type::string()),
'description' => 'Id of user',
],
'posts' => [
'args' => [
'id' => [
'type' => Type::string(),
'description' => 'id of the post',
],
],
'type' => Type::listOf(GraphQL::type('Post')),
'description' => 'post description',
],
];
}public function resolvePostsField($root, $args)
{
if (isset($args['id'])) {
return $root->posts->where('id', $args['id']);
}
return $root->posts;
}

枚举

美剧类型是一个特殊类型的标量变量, 用来限制一系列的允许的数据, 可以查看这里阅读更多的信息

首先创建一个 Enum 作为 GraphQLType 的扩展类型

// app/GraphQL/Enums/EpisodeEnum.php
namespace App\GraphQL\Enums;
use Folklore\GraphQL\Support\Type as GraphQLType;
class EpisodeEnum extends GraphQLType {
protected $enumObject = true;
protected $attributes = [
'name' => 'Episode',
'description' => 'The types of demographic elements',
'values' => [
'NEWHOPE' => 'NEWHOPE',
'EMPIRE' => 'EMPIRE',
'JEDI' => 'JEDI',
],
];
}

注册 Enum 在 config/graphql.phptypes 数组

// config/graphql.php
'types' => [TestEnum' => TestEnumType::class ];

然后如下使用

// app/GraphQL/Type/TestType.php
class TestType extends GraphQLType {
public function fields()
{
return [
'type' => [
'type' => GraphQL::type('TestEnum')
]
]
}
}

接口

你可以使用接口来限制一系列的字段, 阅读更多的消息点击这里

一系列的接口

// app/GraphQL/Interfaces/CharacterInterface.php
namespace App\GraphQL\Interfaces;
use GraphQL;
use Folklore\GraphQL\Support\InterfaceType;
use GraphQL\Type\Definition\Type;
class CharacterInterface extends InterfaceType {
protected $attributes = [
'name' => 'Character',
'description' => 'Character interface.',
]; public function fields() {
return [
'id' => [
'type' => Type::nonNull(Type::int()),
'description' => 'The id of the character.'
],
'appearsIn' => [
'type' => Type::nonNull(Type::listOf(GraphQL::type('Episode'))),
'description' => 'A list of episodes in which the character has an appearance.'
],
];
} public function resolveType($root) {
// Use the resolveType to resolve the Type which is implemented trough this interface
$type = $root['type'];
if ($type === 'human') {
return GraphQL::type('Human');
} else if ($type === 'droid') {
return GraphQL::type('Droid');
}
}
}

类型实现

// app/GraphQL/Types/HumanType.php
namespace App\GraphQL\Types;
use GraphQL;
use Folklore\GraphQL\Support\Type as GraphQLType;
use GraphQL\Type\Definition\Type;
class HumanType extends GraphQLType {
protected $attributes = [
'name' => 'Human',
'description' => 'A human.'
];
public function fields() {
return [
'id' => [
'type' => Type::nonNull(Type::int()),
'description' => 'The id of the human.',
],
'appearsIn' => [
'type' => Type::nonNull(Type::listOf(GraphQL::type('Episode'))),
'description' => 'A list of episodes in which the human has an appearance.'
],
'totalCredits' => [
'type' => Type::nonNull(Type::int()),
'description' => 'The total amount of credits this human owns.'
]
];
}
public function interfaces() {
return [
GraphQL::type('Character')
];
}
}

自定义字段

你同样可以定义一个字段类, 如果你想在多个类型中重用他们.

namespace App\GraphQL\Fields;
use GraphQL\Type\Definition\Type;
use Folklore\GraphQL\Support\Field;
class PictureField extends Field {
protected $attributes = [
'description' => 'A picture'
];
public function type(){
return Type::string();
}
public function args()
{
return [
'width' => [
'type' => Type::int(),
'description' => 'The width of the picture'
],
'height' => [
'type' => Type::int(),
'description' => 'The height of the picture'
]
];
}
protected function resolve($root, $args)
{
$width = isset($args['width']) ? $args['width']:100;
$height = isset($args['height']) ? $args['height']:100;
return 'http://placehold.it/'.$width.'x'.$height;
}
}

你可以在 type 声明中使用他们

namespace App\GraphQL\Type;
use GraphQL\Type\Definition\Type;
use Folklore\GraphQL\Support\Type as GraphQLType;
use App\GraphQL\Fields\PictureField;
class UserType extends GraphQLType {
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 user'
],
//Instead of passing an array, you pass a class path to your custom field
'picture' => PictureField::class
];
}
}

加载关联关系

传递给 query 的 resolve 方法的第三个参数是 GraphQL\Type\Definition\ResolveInfo 的实例, 允许你从请求中取回指定的 key. 下面是一个使用这个参数的例子来获取关联模型的数据. 如下

namespace App\GraphQL\Query;
use GraphQL;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\ResolveInfo;
use Folklore\GraphQL\Support\Query;
use App\User;
class UsersQuery extends Query
{
protected $attributes = [
'name' => 'Users query'
];
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, $context, ResolveInfo $info)
{
$fields = $info->getFieldSelection($depth = 3);
$users = User::query();
foreach ($fields as $field => $keys) {
if ($field === 'profile') {
$users->with('profile');
}
if ($field === 'posts') {
$users->with('posts');
}
}
return $users->get();
}
}

你的 UserType 可能看起来是这个样子的

namespace App\GraphQL\Type;
use Folklore\GraphQL\Support\Facades\GraphQL;
use GraphQL\Type\Definition\Type;
use Folklore\GraphQL\Support\Type as GraphQLType;
class UserType extends GraphQLType
{
/**
* @var array
*/
protected $attributes = [
'name' => 'User',
'description' => 'A user',
];
/**
* @return array
*/
public function fields()
{
return [
'uuid' => [
'type' => Type::nonNull(Type::string()),
'description' => 'The uuid of the user'
],
'email' => [
'type' => Type::nonNull(Type::string()),
'description' => 'The email of user'
],
'profile' => [
'type' => GraphQL::type('Profile'),
'description' => 'The user profile',
],
'posts' => [
'type' => Type::listOf(GraphQL::type('Post')),
'description' => 'The user posts',
]
];
}
}

这样我们有一个 profile 和一个 post 类型作为期待的返回关联关系数据

class ProfileType extends GraphQLType
{
protected $attributes = [
'name' => 'Profile',
'description' => 'A user profile',
];
public function fields()
{
return [
'name' => [
'type' => Type::string(),
'description' => 'The name of user'
]
];
}
}

class PostType extends GraphQLType
{
protected $attributes = [
'name' => 'Post',
'description' => 'A post',
];
public function fields()
{
return [
'title' => [
'type' => Type::nonNull(Type::string()),
'description' => 'The title of the post'
],
'body' => [
'type' => Type::string(),
'description' => 'The body the post'
]
];
}
}

最后你的查询可能是这个样子, 使用 URL

http://homestead.app/graphql?query=query+FetchUsers{users{uuid, email, team{name}}}

推荐阅读
  • 本文介绍了多种Eclipse插件,包括XML Schema Infoset Model (XSD)、Graphical Editing Framework (GEF)、Eclipse Modeling Framework (EMF)等,涵盖了从Web开发到图形界面编辑的多个方面。 ... [详细]
  • 如何撰写适应变化的高效代码:策略与实践
    编写高质量且适应变化的代码是每位程序员的追求。优质代码的关键在于其可维护性和可扩展性。本文将从面向对象编程的角度出发,探讨实现这一目标的具体策略与实践方法,帮助开发者提升代码效率和灵活性。 ... [详细]
  • 在Laravel中实现PHP对JSON数据的发布与处理 ... [详细]
  • 篇首语:本文由编程笔记#小编为大家整理,主要介绍了laravel中抽离公共模版共用数据相关的知识,希望对你有一定的参考价值。 ... [详细]
  • C#爬虫Fiddler插件开发自动生成代码
    哈喽^_^一般我们在编写网页爬虫的时候经常会使用到Fiddler这个工具来分析http包,而且通常并不是分析一个包就够了的,所以为了把更多的时间放在分析http包上,自动化生成 ... [详细]
  • 本文探讨了如何通过Service Locator模式来简化和优化在B/S架构中的服务命名访问,特别是对于需要频繁访问的服务,如JNDI和XMLNS。该模式通过缓存机制减少了重复查找的成本,并提供了对多种服务的统一访问接口。 ... [详细]
  • 本文介绍了一种通过设置主题(Theme)来实现快速启动的Android引导页,并详细说明了如何避免因不同屏幕分辨率导致的图片拉伸问题。 ... [详细]
  • PHP实现汉诺塔算法
    昨天研究了一天汉诺塔算法都没搞懂,感觉自己智商被碾压了,还不如《猩球崛起》中的那一只猩猩!!!起源传说最早发明这个问题的人是法国数学家『爱德华·卢卡斯』。在世界中心贝拿勒斯(在印度 ... [详细]
  • Laravel 开发技巧:如何为集合中的每个元素添加递增编号
    本文将介绍如何在 Laravel 集合中为每个数组元素添加递增的编号,帮助开发者更好地管理和操作数据。 ... [详细]
  • 本文将深入解析 Lumen 框架中的中间件机制,并提供实用的应用指南。我们将从官方文档出发,重点解读 5.3 版本中的相关内容,帮助开发者更好地理解和使用中间件功能。通过具体示例,探讨中间件在请求处理流程中的作用及其配置方法。 ... [详细]
  • 本文详细探讨了Laravel框架中路由和控制器的操作实例,旨在为开发者提供深入的理解和实用的参考。通过具体的示例,读者可以更好地掌握如何在Laravel中配置和使用路由及控制器。此外,文章还提供了丰富的PHP编程技巧和最佳实践,帮助读者提升开发效率和代码质量。 ... [详细]
  • 掌握PHP编程必备知识与技巧——全面教程在当今的PHP开发中,了解并运用最新的技术和最佳实践至关重要。本教程将详细介绍PHP编程的核心知识与实用技巧。首先,确保你正在使用PHP 5.3或更高版本,最好是最新版本,以充分利用其性能优化和新特性。此外,我们还将探讨代码结构、安全性和性能优化等方面的内容,帮助你成为一名更高效的PHP开发者。 ... [详细]
  • 本文探讨了在Lumen框架中实现自定义表单验证功能的方法与挑战。Lumen的表单验证机制默认返回无状态的JSON格式API响应,这给初学者带来了一定的难度。通过深入研究Validate类,作者分享了如何有效配置和使用自定义验证规则,以提升表单数据的准确性和安全性。 ... [详细]
  • 模型花费时间在Laravel中创建新数据时无法按类别保存计算数据publicstaticfunctionfindOrCreate($plan_id,$data){$fromDate ... [详细]
  • 篇首语:本文由编程笔记#小编为大家整理,主要介绍了在Laravel中创建,更新或删除记录时识别sql错误的最佳方法相关的知识,希望对你有一定的参考价值。 ... [详细]
author-avatar
80后女孩香香521
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有