fandogh/graphql

Facebook GraphQL for Laravel

维护者

详细信息

github.com/pi0/laravel-graphql

源代码

支持包维护!
pi0

安装: 13

依赖: 0

建议者: 0

安全性: 0

星标: 0

观察者: 3

分支: 233

类型:项目

v0.4.5 2016-08-04 07:00 UTC

README

使用 Facebook GraphQL 与 Laravel 5。它基于 PHP 实现 这里。您可以在 GraphQL 简介 中了解 GraphQL 的更多信息(在 React 博客上),或者您还可以阅读 GraphQL 规范。这是一个正在进行中的项目。

此包与 Eloquent 模型(或任何其他数据源)兼容。请参阅下面的示例。

安装

依赖

安装

1- 在您的 composer.json 中通过 Composer 引入包。

{
	"require": {
		"folklore/graphql": "0.4.*"
	}
}

2- 运行 Composer 以安装或更新新要求。

$ composer install

$ composer update

3- 将服务提供者添加到您的 app/config/app.php 文件。

'Folklore\GraphQL\GraphQLServiceProvider',

4- 将外观添加到您的 app/config/app.php 文件。

'GraphQL' => 'Folklore\GraphQL\Support\Facades\GraphQL',

5- 发布配置文件

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

6- 查看配置文件

config/graphql.php

使用方法

高级用法

创建查询

首先您需要创建一个类型。

	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'
		];
		
		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 外观将类型添加到服务提供者中。

    
	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 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)
		{
			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();
			}
		}
	
	}

将查询添加到 config/graphql.php 配置文件

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

或使用 GraphQL 外观

    
    GraphQL::addQuery('App\GraphQL\Query\UsersQuery', 'users');

这样就完成了。您应该能够通过向 /graphql(或您在配置中选择的任何内容)的 URL 发送请求来查询 GraphQL。尝试使用以下 query 输入进行 GET 请求

    query FetchUsers {
        users {
            id
            email
        }
    }

例如,如果您使用 homestead

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

创建突变

突变类似于任何其他查询,它接受参数(这些参数将用于执行突变)并返回特定类型的对象。

例如,更新用户密码的突变。首先您需要定义突变。

	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 方法中看到的,您使用参数来更新您的模型并返回它。

然后您将突变添加到 config/graphql.php 配置文件

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

或使用 GraphQL 外观

    
    GraphQL::addMutation('App\GraphQL\Mutation\UpdateUserPasswordMutation', 'updateUserPassword');

然后您应该能够在您的端点上使用以下查询来执行突变。

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

在突变中添加验证

可以为突变添加验证规则。它使用 Laravel 的 Validatorargs 执行验证。

在创建突变时,您可以通过以下方式添加一个方法来定义应用的验证规则

	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' => 'password', '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' => 'password',
					'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 端点时,你可以传递一个 params 参数。

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

自定义字段

如果你想在多个类型中重复使用一个字段,你也可以将其定义为一个类。

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 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;
	}
        
}

然后你可以在你的类型声明中使用它

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'
	];
	
	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' => App\GraphQL\Fields\PictureField::class
		];
	}

}

预加载关系

查询的 resolve 方法传入的第三个参数是 GraphQL\Type\Definition\ResolveInfo 的一个实例,你可以用它来检索请求中的键。以下是一个使用此信息来预加载相关 Eloquent 模型的示例。

你的查询可能看起来像这样

	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, 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();
		}
	}

你的用户类型可能看起来像这样

<?php

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',
            ]
        ];
    }
}

到目前为止,我们有了预期的配置文件和帖子类型

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'
            ]
        ];
    }
}

最后,如果你的查询使用的是 Homestead,那么它可能看起来像这样

例如,如果您使用 homestead

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