尝试全面利用Laravel和GraphQL

首先

2018年Laravel降誕カレンダー- Qiitaの10日目の記事です!

我个人的印象是,大约一年前开始,我开始听到越来越多有关GraphQL的讨论,并且最近我也逐渐发现越来越多的怀疑意见。

    • RestfulライクなAPIの代替案として有効なのか自分で触って確かめてみたかった

 

    Laravelで使い倒す記事を見かけていなかった

因此我尽可能地充分利用了这个机会(虽然只做了一些深入尝试?)。
※我将逐步添加实施例子。

值得一提的是,在這篇文章中

    • GraphQLとは何か

 

    • GraphQLの諸々(クエリ、ミューテーション)の説明

 

    クエリの記述方法の説明

不会说明记录方式,但在使用过程中将列出实际执行的查询。

前提 – 必要的条件或基础。
前提 – 先决条件或假设。
前提 – 开始或展开讨论之前的必要条件。
前提 – 先决条件或基本假设。

PHP版本为7.1.3,Laravel框架版本为5.7.16,Nuwave Lighthouse版本为2.6。

创造的东西

スクリーンショット 2018-12-10 7.45.55.png

使用的库

在使用Laravel时,有几个库可以用于GraphQL,但是这次我们选择了lighthouse作为前提。

我认为这篇文章对于Lighthouse来说写得详细且易懂。

项目成果

我已经把本次的成果放在这里。
※附加的内容尚未反映。

准备下来

为了创建如上所述的ER图结构,我们将创建迁移、关系和种子。
我将省略说明。
如果您感兴趣,可以在成果物内查看。

灯塔系统引入

现在进入正题。
我们将参考这个。

首先需要安装库。

$ composer require nuwave/lighthouse

接下来,使用vendor:publish命令进行初始设置。

$ php artisan vendor:publish --provider="Nuwave\Lighthouse\Providers\LighthouseServiceProvider" --tag=schema

我认为routes/graphql/schema.graphql文件已经完成了。

我们也安装了一个名为laravel-graphql-playground的开发工具。即使在前端等其他地方已经准备了独立的GraphQL客户端,我认为仍然可以使用它来确认模式定义等用途。

$ composer require mll-lab/laravel-graphql-playground

最后,我们还需要将playground发布为vendor并进行初始设置。
有关playground的说明请查看此处。

php artisan vendor:publish --provider="MLL\GraphQLPlayground\GraphQLPlaygroundServiceProvider"

以上是引言完毕。
由于本次未使用外观模式,所以没有进行设置。

执行查询

简单的查询

首先,我们尝试执行一个简单的查询。
我们将在routes/graphql/schema.graphql中注册的查询进行执行。

type Query {
    user(id: ID @eq): User @find(model: "App\\User")
}

只需给出一个选项!

我将通过laravel-graphql-playground进行执行并访问。根据此处的用法,我认为当您访问URL /graphql-playground时会显示内容。如果是在(http://127.0.0.1:8000的环境中,那么URL将是http://127.0.0.1:8000/graphql-playground)。

スクリーンショット 2018-12-09 2.38.09.png

一旦能够访问,我立即尝试发布查询。

query {
  user(id: 1) {
    id
    name
    email
  }
}
スクリーンショット 2018-12-09 2.41.23.png

使用关联查询

接下来,让我们尝试使用关联查询来执行。
我们尝试获取与用户相关联的文章。

首先,我们将创建一个文章类型。

type Article {
    id: ID!
    userId: Int! @rename(attribute: user_id)
    title: String!
    body: String!
    createdAt: DateTime! @rename(attribute: created_at)
    updatedAt: DateTime! @rename(attribute: updated_at)
}

我认为实际上大部分都是前端使用GraphQL,因此我使用@rename指令将列名重命名并转换为驼峰命名法。

接下来,我们将在用户类型中添加文章。

type User {
    id: ID!
    name: String!
    email: String!
+   articles: [Article] @hasMany
    created_at: DateTime! @rename(attribute: created_at)
    updated_at: DateTime! @rename(attribute: updated_at)
}

由于准备完毕,现在将执行使用关系型数据库的查询语句。

query {
  user(id: 2) {
    id
    name
    email
    articles {
      id
      userId
      title
    }
  }
}
スクリーンショット 2018-12-09 2.57.06.png

获取分页器的数据查询

最后,我们将获取多个数据。因为在routes/graphql/schema.graphql中注册了查询,所以我们将执行该查询。

type Query {
    users: [User!]! @paginate(type: "paginator" model: "App\\User")
}

由于在paginator中必须提供count参数,所以我会将其添加进去。

query {
  users(
    count: 10
  ) {
    data {
      id
      name
      email
      articles {
        id
        userId
        title
      }
    }
    paginatorInfo {
      currentPage
    }
  }
}
スクリーンショット 2018-12-09 9.13.05.png

当获取多个数据时,

    • ベースとなるモデルのhasMany等で取得する

 

    paginatorで取得する(typeは2種類)

我想,可能只有两个选择。
我想知道是否有人想将基础模型作为没有分页器的纯粹集合拉出来,如果是这样的话,我认为那将是你自己制作的解析器注册。(如果您有不需要创建解析器也可以完成的信息,请务必留下评论,我会非常感激)

因为 Playground 可以根据源代码生成模式信息,所以它为我提供了一个选项。

    • どんなクエリがある?

 

    このクエリの引数、戻り値は?

我希望在你感到困惑的时候能够参考相关的模式信息。

スクリーンショット 2018-12-09 9.18.42.png
スクリーンショット 2018-12-09 9.26.31.png

然而,由于不支持热重载,所以如果修改源代码,需要重新加载页面。

进行突变

注册

现在我已经可以执行查询并尝试进行变更操作。
首先,我将注册一个用户。

对于在routes/graphql/schema.graphql注册的变异进行一些修改。

type Mutation {
    createUser(
        name: String
            @rules(apply: ["required"])
        email: String
            @rules(apply: ["required",
                "email",
                "unique:users,email"]
            )
        password: String
            @bcrypt
            @rules(apply: ["required"])
    ): User
        @create(model: "App\\User")
}

以下是注册的Mutation的样子。

mutation {
  createUser(
    name: "taro"
    email: "graphql@example.com"
    password: "secret"
  ) {
    id
    name
    email
  }
}
スクリーンショット 2018-12-09 9.36.17.png

更新 –

我会进行更新处理。
这里使用的是原本就有的东西。

type Mutation {
    updateUser(
        id: ID
            @rules(apply: ["required"])
        name: String
        email: String
            @rules(apply: ["email"])
    ): User
        @update(model: "App\\User")
}

我尝试进行更新。

mutation {
  updateUser(
    id: 51
    name: "hanako"
  ) {
    id
    name
  }
}
スクリーンショット 2018-12-09 9.36.17.png

删除 chú)

我們最後也會進行刪除。

我们将使用原来就存在的东西。

type Mutation {
    deleteUser(
        id: ID @rules(apply: ["required"])
    ): User @delete(model: "App\\User")
}

我试试删除。

mutation {
  deleteUser(
    id: 51
  ) {
    id
    name
  }
}
スクリーンショット 2018-12-09 9.44.34.png

根据消息,将返回值更改为必需,并重新执行。

type Mutation {
    deleteUser(
-       id: ID @rules(apply: ["required"])
+       id: ID! @rules(apply: ["required"])
    ): User @delete(model: "App\\User")
}
スクリーンショット 2018-12-09 9.47.06.png

添加查询和改变动作

为了充分利用,我们将添加一些查询和变更。

使用基于LIKE的搜索条件

定义是这样的,

type Query {
    usersByEmail(email: String @where(operator: "like")): [User!]!
        @paginate(type: "paginator" model: "App\\User")
}

这样执行。

query {
  usersByEmail(
    email: "%r%"
    count: 10
  ) {
    data {
      id
      email
    }
  }
}

@where指令,在官方的主分支中有记录,但在ver2.6分支中未找到,让我感到有点困惑。

只需一个选项,将以下内容用中文进行意译:

删除突变以外的ID指定

根据源代码,看起来无法指定ID以外的内容来执行@delete指令,所以我将自己编写解析器。

首先,使用artisan生成文件。

$ php artisan lighthouse:mutation DeleteUsersByEmail

这次

    • 指定した文字列でEmailのLIKE検索を検索をし、該当したユーザーを削除する

 

    戻り値に適当な値をセットする

我制作了一个满足条件的解析器。

<?php

namespace App\Http\GraphQL\Mutations;

use GraphQL\Type\Definition\ResolveInfo;
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;
use App\User;

class DeleteUsersByEmail
{
    /**
     * Return a value for the field.
     *
     * @param null $rootValue Usually contains the result returned from the parent field. In this case, it is always `null`.
     * @param array $args The arguments that were passed into the field.
     * @param GraphQLContext|null $context Arbitrary data that is shared between all fields of a single query.
     * @param ResolveInfo $resolveInfo Information about the query itself, such as the execution state, the field name, path to the field from the root, and more.
     *
     * @return mixed
     */
    public function handle(
        $rootValue,
        array $args,
        GraphQLContext $context = null,
        ResolveInfo $resolveInfo
    ) {
        $email = $args['email'];
        User::where('email', 'like', $email)
            ->delete();

        $res = 'ok';

        return compact('res');
    }
}

接下来,使用自己创建的解析器进行定义。

type DummyResponse {
    res: String!
}

type Mutation {
    deleteUsersByEmail(
        email: String!  @rules(apply: ["required"])
    ): DummyResponse
        @field(resolver: "App\\Http\\GraphQL\\Mutations\\DeleteUsersByEmail@handle")
}

最后,我们以这样的方式进行执行。

mutation {
  deleteUsersByEmail(
    email: "%r%"
  ) {
    res
  }
}

将定义文件分割为多个部分

由于仅使用routes/graphql/schema.graphql来完成可能很困难,所以我尝试按照每个类型进行分割。

首先,将routes/graphql/schema.graphql修改为以下的样子。

scalar DateTime @scalar(class: "Nuwave\\Lighthouse\\Schema\\Types\\Scalars\\DateTime")

scalar Date @scalar(class: "Nuwave\\Lighthouse\\Schema\\Types\\Scalars\\Date")

# その他ファイルをextend typeする為にここに空のベースとなる定義を配置しておく
type Query
type Mutation

#import models/*.graphql

接下来,我们来看看如何将分割后的文件处理成这个样子。

extend type Query {
    users: [User!]! @paginate(type: "paginator" model: "App\\User")
    user(id: ID @eq): User @find(model: "App\\User")
    usersByEmail(email: String @where(operator: "like")): [User!]!
        @paginate(type: "paginator" model: "App\\User")
}

extend type Mutation {
    createUser(
        name: String
            @rules(apply: ["required"])
        email: String
            @rules(apply: ["required",
                "email",
                "unique:users,email"]
            )
        password: String
            @bcrypt
            @rules(apply: ["required"])
    ): User
    @create(model: "App\\User")
    updateUser(
        id: ID
            @rules(apply: ["required"])
        name: String
        email: String
            @rules(apply: ["email"])
    ): User
        @update(model: "App\\User")
    deleteUser(
        id: ID! @rules(apply: ["required"])
    ): User
        @delete(model: "App\\User")
    deleteUsersByEmail(
        email: String!  @rules(apply: ["required"])
    ): DummyResponse
        @field(resolver: "App\\Http\\GraphQL\\Mutations\\DeleteUsersByEmail@handle")
}

type DummyResponse {
    res: String!
}

type User {
    id: ID!
    name: String!
    email: String!
    password: String!
    articles: [Article] @hasMany
    createdAt: DateTime! @rename(attribute: created_at)
    updatedAt: DateTime! @rename(attribute: updated_at)
}

type Article {
    id: ID!
    userId: Int! @rename(attribute: user_id)
    title: String!
    body: String!
    createdAt: DateTime! @rename(attribute: created_at)
    updatedAt: DateTime! @rename(attribute: updated_at)
}

只能调用一次type Query type Mutation等,所以在schema.graphql方面处理。

# その他ファイルをextend typeする為にここに空のベースとなる定義を配置しておく
type Query
type Mutation

在分割的文件中,我们会先定义一个空的类型,然后始终使用 extend type Query 等方式进行扩展。

自定义错误信息

如果实际使用的话,我认为需要自定义错误消息,所以我会在更新用户的处理中尝试一下。

extend type Mutation
    updateUser(
        id: ID
            @rules(
                apply: ["required"],
                messages: { required: "idは必須です" }
            )
        name: String
        email: String
            @rules(apply: ["email"])
    ): User
        @update(model: "App\\User")
}
スクリーンショット 2018-12-09 10.44.51.png

当graphql-playground无法正常工作时的应对措施是什么?

有时候,当执行错误的查询描述时,Graphql Playground 可能会突然无法使用。

在我苦恼结构问题无法继续的时候,在Twitter上发了一条帖子,得到了帮助!

这个问题和那个一样吗?https://t.co/IzfTnFPa0b— FUJI Goro (@__gfx__) 2018年12月3日

请注意,我认为每个人都会遇到一次。

【2018/12/20补充】使用Datetime时的注意事项。

默认定义的

scalar DateTime @scalar(class: "Nuwave\\Lighthouse\\Schema\\Types\\Scalars\\DateTime")

这个日期时间的话,

type User {
    id: ID!
    ...省略
    emailVerifiedAt: DateTime @rename(attribute: email_verified_at)
    createdAt: DateTime @rename(attribute: created_at)
    updatedAt: DateTime @rename(attribute: updated_at)
}

在使用type时需要注意。

如果不指定$dates,会报错,所以请务必在Model中指定$dates。

(如果只有created_at和updated_at这两个字段,可以不显式添加,但考虑到还有其他字段,最好全部添加。)

class User extends Authenticatable
{
    // 省略

    // $datesで指定しておく
    protected $dates = [
        'email_verified_at', 'created_at', 'updated_at'
    ];
}

【2018/12/27更新】批量执行多个查询

我追加了有关GraphQL最大优点的描述,即可以将端点集中在一起。

query multiQuerySample(
  $user1Id: ID
  $user2Id: ID
) {
  user1: user(id: $user1Id) {
    id
  }
  user2: user(id: $user2Id) {
    id
  }
}

以这种方式,您可以同时执行多个查询。

スクリーンショット 2018-12-27 15.55.17.png

通过这个方法,您可以轻松地解决频繁调用 RestAPI 的痛苦!

【2019/01/10添加】批量注册多个数据

我想有时候可能会有一次性注册多个数据的情况。
虽然我不确定这种方法是否正确,但我会附加说明。

最终目标

我希望通过执行以下查询来实现批量注册多个用户。

mutation {
    createUsers(users: [
        {name: "taro", email: "taro@example.com", password: "xxxxxxxx"},
        {name: "hanako", email: "hanako@example.com", password: "xxxxxxxx"}
    ])
    {
      res
    }
}

接收数组型数据

我认为要注册多个项目,需要将数组类型的数据传递给GraphQL,但我认为可能需要定义标量才能获取。(如果我说错了,请您指正,谢谢)

所以,首先我们需要定义一个独特的标量来设置数组的类型。

从命令行界面创建一个标量。

$ php artisan lighthouse:scalar Users

执行后,将在 app/GraphQL/Scalars 目录下创建一个名为 Users.php 的文件。

接下来将开始实现内容。

首先,这里是刚创建的文件的内容。

<?php

namespace App\Http\GraphQL\Scalars;

use GraphQL\Language\AST\Node;
use GraphQL\Type\Definition\ScalarType;

/**
 * Read more about scalars here http://webonyx.github.io/graphql-php/type-system/scalar-types/
 */
class Users extends ScalarType
{
    /**
     * Serializes an internal value to include in a response.
     *
     * @param string $value
     * @return string
     */
    public function serialize($value)
    {
        // Assuming the internal representation of the value is always correct
        return $value;

        // TODO validate if it might be incorrect
    }

    /**
     * Parses an externally provided value (query variable) to use as an input
     *
     * @param mixed $value
     * @return mixed
     */
    public function parseValue($value)
    {
        // TODO implement validation

        return $value;
    }

    /**
     * Parses an externally provided literal value (hardcoded in GraphQL query) to use as an input.
     *
     * E.g.
     * {
     *   user(email: "user@example.com")
     * }
     *
     * @param Node $valueNode
     * @param array|null $variables
     *
     * @return mixed
     */
    public function parseLiteral($valueNode, array $variables = null)
    {
        // TODO implement validation

        return $valueNode->value;
    }
}

我可能会提供一些补充的评论,但让我大致解释一下每个函数的作用。

    • serialize

DBから取得する際に値を変換する為の関数

parseValue

引数を変数で受け取った値を検証、加工する為の関数

parseLiteral

引数を直接受け取った値(変数定義せずクエリに直接指定する場合)を検証、加工する為の関数

我觉得如果看一下最初创建的 Nuwave\Lighthouse\Schema\Types\Scalars\Datetime 可能会有所启发,所以为了保险起见,我会把它放上来。

<?php

namespace Nuwave\Lighthouse\Schema\Types\Scalars;

use Carbon\Carbon;
use GraphQL\Error\Error;
use GraphQL\Utils\Utils;
use GraphQL\Type\Definition\ScalarType;
use GraphQL\Language\AST\StringValueNode;

class DateTime extends ScalarType
{
    public function serialize($value): string
    {
        return $value->toAtomString();
    }

    public function parseValue($value): Carbon
    {
        try {
            $dateTime = Carbon::createFromFormat(Carbon::DEFAULT_TO_STRING_FORMAT, $value);
        } catch (\Exception $e) {
            throw new Error(Utils::printSafeJson($e->getMessage()));
        }

        return $dateTime;
    }

    public function parseLiteral($valueNode, array $variables = null): Carbon
    {
        if (! $valueNode instanceof StringValueNode) {
            throw new Error('Query error: Can only parse strings got: '.$valueNode->kind, [$valueNode]);
        }

        try {
            $dateTime = Carbon::createFromFormat(Carbon::DEFAULT_TO_STRING_FORMAT, $valueNode->value);
        } catch (\Exception $e) {
            throw new Error(Utils::printSafeJson($e->getMessage()));
        }

        return $dateTime;
    }
}

我們現在開始實際實施內容。
從網絡上的樣本來看,對於日期類型、電子郵件地址等基本值通常會添加某種控制,但這次由於要使用陣列,我們需要考慮GraphQL內部的類型。
結果是這樣的。

<?php

namespace App\Http\GraphQL\Scalars;

use GraphQL\Language\AST\Node;
use GraphQL\Type\Definition\ScalarType;
use GraphQL\Error\Error;
use GraphQL\Language\AST\ListValueNode;
use GraphQL\Language\AST\ObjectValueNode;
use GraphQL\Language\AST\ObjectFieldNode;

class Users extends ScalarType
{
    public function serialize($value)
    {
        return $value;
    }

    public function parseValue($value)
    {
        return $value;
    }

    public function parseLiteral($valueNode, array $variables = null)
    {
        // 今回はデータが配列であるかどうかだけをチェックしていますが、実際はもう少ししっかりチェックすることになると思います
        if (!$valueNode instanceof ListValueNode) {
            throw new Error('Query error: Can only parse List got: '.$valueNode->kind, [$valueNode]);
        }

        return $this->argValue($valueNode);
    }

    /**
     * GraphQLが持つ型から最終的な配列データを取得する
     * 
     * @param $arg mixed
     * @return array
     */
    private function argValue($arg)
    {
        if ($arg instanceof ListValueNode) {
            return collect($arg->values)->map(function ($node) {
                return $this->argValue($node);
            })->toArray();
        }

        if ($arg instanceof ObjectValueNode) {
            return collect($arg->fields)->mapWithKeys(function ($field) {
                return [$field->name->value => $this->argValue($field)];
            })->toArray();
        }

        if ($arg instanceof ObjectFieldNode) {
            return $this->argValue($arg->value);
        }

        return $arg->value;
    }
}

通过查看以上实例,可以看出argValue的内容非常复杂且相当繁琐。
我根据Nuwave\Lighthouse\Support\Traits\HandlesDirectives中的Trait中的argValue进行了参考,并稍微进行了整理来创建它。

我认为到目前为止,应该可以接收参数了。

创建一个用于注册多个数据的突变。

因为我觉得也许有没有使用自己编写的解析器来实现变异的方法,所以我要创建一个变异。具体的创建步骤已在上述说明中写明,所以我会省略细节。

$ php artisan lighthouse:mutation CreateUsers

我使用上述命令创建了一个文件,并按照以下方式实施。

<?php

namespace App\Http\GraphQL\Mutations;

use GraphQL\Type\Definition\ResolveInfo;
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;
use App\User;

class CreateUsers
{
    public function resolve($rootValue, array $args, GraphQLContext $context = null, ResolveInfo $resolveInfo)
    {
        User::insert($args['users']);

        $res = 'ok';
        return compact('res');
    }
}

突變只需要這麼簡單就可以了。

如果最后记述实际突变的定义,那就完成了。

scalar Users @scalar(class: "App\\Http\\GraphQL\\Scalars\\Users")

extend type Mutation {
    createUsers(
        users: Users
    ): DummyResponse
    @field(resolver: "App\\Http\\GraphQL\\Mutations\\CreateUsers@resolve")
}

由于上述工作已经完成,现在我们来实际执行一下!

スクリーンショット 2019-01-10 17.00.45.png

我成功地注册了多个数据!

【2019/01/28更新】进行排序订单

我希望尽快在官方中实现,但目前要使用order by功能,需要自己创建指令(或通过解析器解决)。
我会继续介绍指令添加方法。

达到目标

我将尝试用这种查询样式进行排序。

query {
  users(
    count: 3
    queryOrder: {
      column: "id",
      order: DESC
    }
  ) {
    data {
      id
    }
  }
}

创建自定义指令。

首先创建自定义指令。

Directiveの設定が行えるようです。

    /*
    |--------------------------------------------------------------------------
    | Directives
    |--------------------------------------------------------------------------
    |
    | List directories that will be scanned for custom server-side directives.
    |
    */
    'directives' => [__DIR__.'/../app/Http/GraphQL/Directives'],

根据@eq指令所在的Nuwave\Lighthouse\Schema\Directives\Args\EqualsFilterDirective,将其复制粘贴到指定的目录中创建。

看起来就是这个样子。


```<?php

namespace Nuwave\Lighthouse\Schema\Directives\Args;

use Nuwave\Lighthouse\Schema\Values\ArgumentValue;
use Nuwave\Lighthouse\Schema\Directives\BaseDirective;
use Nuwave\Lighthouse\Support\Contracts\ArgMiddleware;
use Nuwave\Lighthouse\Support\Traits\HandlesQueryFilter;

class EqualsFilterDirective extends BaseDirective implements ArgMiddleware
{
    use HandlesQueryFilter;

    /**
     * Name of the directive.
     *
     * @return string
     */
    public function name(): string
    {
        return 'eq';
    }

    /**
     * Resolve the field directive.
     *
     * @param ArgumentValue $argument
     * @param \Closure       $next
     *
     * @return ArgumentValue
     */
    public function handleArgument(ArgumentValue $argument, \Closure $next): ArgumentValue
    {
        $this->injectFilter(
            $argument,
            function ($query, string $columnName, $value) {
                return $query->where($columnName, $value);
            }
        );

        return $next($argument);
    }
}

只需更改上述的 injectFilter ,看起来就可以进行了吧?我认为你可以猜到这一点。所以,我会试着按那个方向去做。

<?php

namespace App\Http\GraphQL\Directives;

use Nuwave\Lighthouse\Schema\Values\ArgumentValue;
use Nuwave\Lighthouse\Schema\Directives\BaseDirective;
use Nuwave\Lighthouse\Support\Contracts\ArgMiddleware;
use Nuwave\Lighthouse\Support\Traits\HandlesQueryFilter;

class OrderByDirective extends BaseDirective implements ArgMiddleware
{
    use HandlesQueryFilter;

    /**
     * Name of the directive.
     *
     * @return string
     */
    public function name()
    {
        return 'orderBy';
    }

    /**
     * Resolve the field directive.
     *
     * @param ArgumentValue $argument
     * @param \Closure       $next
     *
     * @return ArgumentValue
     */
    public function handleArgument(ArgumentValue $argument, \Closure $next)
    {
        $this->injectFilter(
            $argument,
            function ($query, string $columnName, $value) {
                // ここでOrder Byをする
                return $query->orderBy($value['column'], array_key_exists('order', $value) ? $value['order'] : 'asc');
            }
        );

        return $next($argument);
    }
}

到此为止,指令方面的处理已经完成。

接受参数

这次我们将像@eq一样使用ArgMiddleware接口来接收参数。本次的目标是针对单个项目进行排序,但仍然需要两个选项,即列升序/降序。因此,我们将进行设置以接收两个值。

- users: [User!]! @paginate(type: "paginator" model: "App\\User")
+ users(queryOrder: QueryOrder @orderBy): [User!]! @paginate(type: "paginator" model: "App\\User")
+ 
+ input QueryOrder {
+     column: String!
+     order: Order = ASC
+ }
+ 
+ enum Order {
+     ASC @enum(value: "ASC")
+     DESC @enum(value: "DESC")
+ }

因为现在可以将此作为参数接收,所以让我试着执行一下!

我已经以正确的排序顺序成功获取了数据!

スクリーンショット 2019-01-28 18.45.38.png

【2019/02/07更新】关于ID类型的注意事项。

我最近第一次了解到,ID在這裡是以String形式存在的。對於Laravel的標準ID,它是以Int形式存在的,所以在設置ID時不要被示例誤導,應該設定為Int。

最后

虽然说要充分使用,但最后却没有充分使用就结束了?

我试用了Laravel的GraphQL库中似乎最活跃的Lighouthouse,然而仍然感觉它并没有那么成熟。
当遇到困难时,我认为查看这方面的源代码可以解决问题。
如果无法解决,我建议尝试创建resolver,可以在官方网站上找到相关信息。

スクリーンショット 2018-12-09 10.48.03.png

以这种方式,我觉得如果自己也以培养开源软件的意识来生活,会感到很有趣!(虽然我自己还没有提升我的公众形象?)

在我们触及之前,关于是否能成为替代Restful风格API的讨论。

    まとめて操作出来るのでAPI発行回数が少なくて済むってメリットがあるから複数のAPIを叩かなきゃいけないところだけGraphQL使って、それ以外は今まで通りRestfulライクなAPIを叩く感じになるかぁ

想着这样,当我亲身触摸时

    • SwaggerDocのように鬼のようなコードを書かずにドキュメントが生成出来る

 

    DevToolsも使いやすい

因为有一种令人感动的情感,我觉得将除了认证API之外的所有内容都整合到GraphQL中也是可行的。

我还没有开始接触Code生成器的相关内容,但是我在考虑一旦codegen得到完善,它可能与TypeScript更加兼容,从而一举成为替代Restful API的选择。我想根据这篇文章或其他的内容,在某个时机尝试一下。

我认为Lighouthouse目前仍有很大的发展空间,因此可以自由加入Slack工作空间,且PR也受到热烈欢迎,我稍微想过能为其成长做出一点贡献就好?

由于我仍处于GraphQL的初学者阶段,对于本文的内容若有任何问题或建议,敬请在评论中指正???!!!

广告
将在 10 秒后关闭
bannerAds