[譯+] Laravel GraphQL ReadMe 文檔

原文地址:php

使用

語法 / Schemas

從 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.phptypes 數組

// 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}}}
相關文章
相關標籤/搜索