結合 Laravel 初步學習 GraphQL

按照官網所述的:php

A query language for your API 一種用於 API 的查詢語言laravel

GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. GraphQL provides a complete and understandable description of the data in your API, gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools.git

GraphQL 既是一種用於 API 的查詢語言也是一個知足你數據查詢的運行時。 GraphQL 對你的 API 中的數據提供了一套易於理解的完整描述,使得客戶端可以準確地得到它須要的數據,並且沒有任何冗餘,也讓 API 更容易地隨着時間推移而演進,還能用於構建強大的開發者工具。github

主要有如下幾個特色:bash

  1. 請求你所要的數據很少很多。向你的 API 發出一個 GraphQL 請求就能準確得到你想要的數據,很少很多。 GraphQL 查詢老是返回可預測的結果。
  2. 獲取多個資源只用一個請求。GraphQL 查詢不只可以得到資源的屬性,還能沿着資源間引用進一步查詢。典型的 REST API 請求多個資源時得載入多個 URL,而 GraphQL 能夠經過一次請求就獲取你應用所需的全部數據。這樣一來,即便是比較慢的移動網絡鏈接下,使用 GraphQL 的應用也能表現得足夠迅速。
  3. 描述全部的可能類型系統。GraphQL API 基於類型和字段的方式進行組織,而非入口端點。你能夠經過一個單一入口端點獲得你全部的數據能力。GraphQL 使用類型來保證應用只請求可能的數據,還提供了清晰的輔助性錯誤信息。應用可使用類型,而避免編寫手動解析代碼。
  4. API 演進無需劃分版本。給你的 GraphQL API 添加字段和類型而無需影響現有查詢。老舊的字段能夠廢棄,從工具中隱藏。經過使用單一演進版本,GraphQL API 使得應用始終可以使用新的特性,並鼓勵使用更加簡潔、更好維護的服務端代碼。
  5. 使用你現有的數據和代碼。GraphQL 讓你的整個應用共享一套 API,而不用被限制於特定存儲引擎。GraphQL 引擎已經有多種語言實現,經過 GraphQL API 可以更好利用你的現有數據和代碼。你只須要爲類型系統的字段編寫函數,GraphQL 就能經過優化併發的方式來調用它們。

Demo

先寫一個 Demo 來看看如何結合 Laravel 使用 GraphQL。網絡

引入 rebing/graphql-laravel

composer require "rebing/graphql-laravel"
複製代碼

由於 Laravel 5.5 開始,有「包自動發現」mp.weixin.qq.com/s/AD05BiKjP…功能,因此 Laravel 5.5 能夠不用手動引入該 provider 和 aliase。以前的版本須要引入對應的 provider 和 aliase。併發

"extra": {
    "laravel": {
        "providers": [
            "Rebing\\GraphQL\\GraphQLServiceProvider"
        ],
        "aliases": {
            "GraphQL": "Rebing\\GraphQL\\Support\\Facades\\GraphQL"
        }
    }
}
複製代碼

建立 Type 和 Query

Type: 經過 Type,能夠幫助咱們格式化查詢結果的類型,主要有 boolean、string、float、int 等,同時也能夠自定義類型composer

Query: 經過 Query,能夠獲取咱們須要的數據。ide

在項目根目錄建立 GraphQL 文件件用於存放 Type 和 Query函數

定義 UsersType:

<?php
/** * User: yemeishu */

namespace App\GraphQL\Type;

use App\User;
use GraphQL\Type\Definition\Type;
use Rebing\GraphQL\Support\Facades\GraphQL;
use Rebing\GraphQL\Support\Type as GraphQLType;

class UsersType extends GraphQLType {
    protected $attributes = [
        'name' => 'Users',
        'description' => 'A type',
        'model' => User::class, // define model for users type
    ];

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

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

定義 Query:

<?php
/** * User: yemeishu */

namespace App\GraphQL\Query;

use App\User;
use GraphQL\Type\Definition\Type;
use Rebing\GraphQL\Support\Facades\GraphQL;
use Rebing\GraphQL\Support\Query;
use Rebing\GraphQL\Support\SelectFields;

class UsersQuery extends Query {
    protected $attributes = [
        'name' => 'users',
        'description' => 'A query of users'
    ];

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

    // arguments to filter query
    public function args() {
        return [
            'id' => [
                'name' => 'id',
                'type' => Type::int()
            ],
            'email' => [
                'name' => 'email',
                'type' => Type::string()
            ]
        ];
    }

    public function resolve($root, $args, SelectFields $fields) {
        $where = function ($query) use ($args) {
            if (isset($args['id'])) {
                $query->where('id',$args['id']);
            }

            if (isset($args['email'])) {
                $query->where('email',$args['email']);
            }
        };
        $users = User::with(array_keys($fields->getRelations()))
            ->where($where)
            ->select($fields->getSelect())
            ->get();

        return $users;
    }
}
複製代碼

配置 graphql.php

將寫好的 UsersType 和 UsersQuery 註冊到 GraphGL 配置文件中。

測試

咱們主要有兩種途徑用於測試,第一種就是向測試 RESTful 接口同樣,使用 Postman:

另外一種方式就是利用 GraphiQL:

An in-browser IDE for exploring GraphQL. https://github.com/graphql/graphiql

這裏咱們使用 noh4ck/graphiql

// 1. 安裝插件
composer require "noh4ck/graphiql:@dev"

// 2. 加入 provider
Graphiql\GraphiqlServiceProvider::class

// 3. 命令
artisan graphiql:publish
複製代碼

配置文件可看出 route 爲:/graphql-ui

運行結果:

還能夠經過傳入參數 (id: 1) 來篩選數據:

Mutation

經過 Demo,咱們初步瞭解 GraphQL 的 Query 查詢方法,接下來咱們看看 Mutation 的用法。

若是說 Query 是 RESTful 的「查」,那麼 Mutation 充當的做用就是「增、刪、改」了。

在 GraphQL 文件夾下建立「Mutation」文件夾,存放和 Mutation 相關的類。

Create Mutation Class

<?php
/** * User: yemeishu * Date: 2018/4/3 */

namespace App\GraphQL\Mutation;

use GraphQL\Type\Definition\Type;
use Rebing\GraphQL\Support\Facades\GraphQL;
use Rebing\GraphQL\Support\Mutation;
use App\User;

class NewUserMutation extends Mutation {
    protected $attributes = [
        'name' => 'NewUser'
    ];

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

    public function args() {
        return [
            'name' => [
                'name' => 'name',
                'type' => Type::nonNull(Type::string())
            ],
            'email' => [
                'name' => 'email',
                'type' => Type::nonNull(Type::string())
            ],
            'password' => [
                'name' => 'password',
                'type' => Type::nonNull(Type::string())
            ]
        ];
    }
    public function resolve($root, $args) {
        $args['password'] = bcrypt($args['password']);
        $user = User::create($args);

        if (!$user) {
            return null;
        }

        return $user;
    }
}
複製代碼

Update Mutation Class

<?php
/** * User: yemeishu * Date: 2018/4/3 */

namespace App\GraphQL\Mutation;

use GraphQL\Type\Definition\Type;
use Rebing\GraphQL\Support\Facades\GraphQL;
use Rebing\GraphQL\Support\Mutation;
use App\User;

class UpdateUserMutation extends Mutation {
    protected $attributes = [
        'name' => 'UpdateUser'
    ];

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

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

    public function resolve($root, $args) {
        $user = User::find($args['id']);
        if (!$user) {
            return null;
        }
        $user->name = $args['name'];
        $user->save();
        return $user;
    }
}
複製代碼

配置 graphql.php

把 NewUserMutation 和 UpdateUserMutation 加入 graphql mutation 配置中

測試

如上圖,建立兩個 mutation,能夠選擇任意一個看運行效果。

建立一個 User:

更新「id: 1」用戶信息:

其中在 graphql-ui 界面,右上角還能夠看到「Docs」,點開能夠查看這兩個 mutiation 的說明:

總結

經過簡單的「增改查」User 來初步瞭解 GraphQL 的 Query 和 Mutation 的使用,接下來能夠將 GraphQL 做爲微服務的「網關」層的前一層來使用。

其中,推薦一篇文章給你們:微服務下使用GraphQL構建BFF | 洞見mp.weixin.qq.com/s/HSIp5PL-s…

「未完待續」

相關文章
相關標籤/搜索