原文地址:php
從 1.0 版本開始, 能夠定義多個語法, 若是您想要一個公共的入口,另外一個須要身份驗證的入口,那麼擁有多個語法是很是有用的。laravel
您能夠在配置中定義多個語法:git
'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 來添加語法github
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' ] ]);
你能夠經過指定的語法來訪問app
// 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}}
首先你須要建立一個類型ide
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
文件中post
'types' => [ 'User' => 'App\GraphQL\Type\UserType' ]
你也可使用 GraphQL Facade 來進行添加, 添加到 service provider 中ui
GraphQL::addType('App\GraphQL\Type\UserType', 'User');
而後, 你須要定義一個查詢而且返回這個類型(或者列表). 你一樣也能夠在指定的參數, 這些參數能夠用在 resolve 方法中.this
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 的擴展類型
<?php // 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.php
的 types
數組
// config/graphql.php 'types' => [TestEnum' => TestEnumType::class ];
而後以下使用
<?php // app/GraphQL/Type/TestType.php class TestType extends GraphQLType { public function fields() { return [ 'type' => [ 'type' => GraphQL::type('TestEnum') ] ] } }
你可使用接口來限制一系列的字段, 閱讀更多的消息點擊這裏
一系列的接口
<?php // 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'); } } }
類型實現
<?php // 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 可能看起來是這個樣子的
<?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', ] ]; } }
這樣咱們有一個 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}}}