【问题标题】:Complex Laravel, Graphql and Lighhouse implementation复杂的 Laravel、Graphql 和 Lighthouse 实现
【发布时间】:2020-12-14 17:00:07
【问题描述】:

我的问题与如何构建复杂的自定义解析器有关,以及为什么它们不能很好地与内置解析器配合使用。我找不到任何关于复杂解析器的好例子,而我的真实案例比这个例子还要复杂。

我有以下架构

type Query {
    users: [User!]! @field(resolver: "App\\Library\\UserController@fetchAll")
    posts: [Post!]! @field(resolver: "App\\Library\\PostController@fetchAll")
    post(id: Int! @eq): Post @find
}

type User {
    id: ID!
    name: String
    posts: [Post!]!  @field(resolver: "App\\Library\\PostController@fetchAll")
}

type Post {
    id: ID!
    content: String!
    comments: [Comment] @field(resolver: "App\\Library\\CommentController@fetchAll")
}

type Comment {
    id: ID!
    reply: String!
commentRating: [CommentRating] @field(resolver: “App\\Library\\CommentRatingController@fetchSum")
}

type CommentRating {
    id: ID!
    rating: String
}

例如我有这个查询

{
  users {
    id,
    name
    posts {
      title
      comments {
        id,
        reply
        
      }
    }
  }
}

由于业务逻辑,我需要自定义解析器,但不是全部。上面的工作(我故意为所有这些都使用自定义解析器,我会稍微解释一下)但前提是我构建了我的 在第一个被正确调用的解析器中的雄辩查询。像这样

// Function in custom resolver. All other custom resolver which are accessed can just pass the $rootValue on, or operate on it.
public function fetchAll($rootValue, array $args, GraphQLContext $context, ResolveInfo $resolveInfo)
{
// We have some more sophisticated logic to dynamically build the array parameter on the line below, because the query may not always request comments, which means 'posts.comments' wont be needed. As this is the entrypoint, $rootValue is empty
    $t = User::with['posts', 'posts.comments', 'posts.comments.ratings'])->get();

    // Business logic modules called here
        return $t;
}

如果我从自定义解析器开始,但查询中的某些内容使用了内置解析器,例如,如果更改

type User {
    id: ID!
    name: String
    posts: [Post!]!  @field(resolver: "App\\Library\\PostController@fetchAll")
}

type User {
    id: ID!
    name: String
    posts: [Post!]!  @all
}

然后它仍然可以正常运行,但引入了 N+1 问题。因此,我可以在我的 mysql 日志中看到突然运行多个查询,如果我只有自定义或仅内置解析器,则不会发生这种情况。让自定义解析器调用内置解析器是不好的做法吗?

最好只为我的所有类型坚持自定义解析器吗?我构建自定义解析器的方法是否正确? (参考公共函数fetchAll代码n-p)

【问题讨论】:

  • 内置解析器无法知道您的解析器中发生了什么。为了解决 N+1 内置解析器的问题,请使用批量加载功能(它有点收集所有需要的 ID,将查询发送到 DB)。我不知道,是否可以在您的自定义解析器中重用它们。

标签: laravel graphql laravel-lighthouse


【解决方案1】:

您可以将解析器类映射到您的架构中,例如

type Query {
    users: [User] @field(resolver: "App\\GraphQL\\Queries\\User@FooFunction")
}

并使用此命令生成此查询解析器类:

php artisan lighthouse:query User

并将您喜欢的每个查询放在这个名为 FooFunction 的函数上:

<?php

namespace App\GraphQL\Queries;

use Carbon\Carbon;
use GraphQL\Type\Definition\ResolveInfo;
use Illuminate\Support\Facades\DB;
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;

class User
{
    /**
     * 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  mixed[]  $args The arguments that were passed into the field.
     * @param  \Nuwave\Lighthouse\Support\Contracts\GraphQLContext  $context Arbitrary data that is shared between all fields of a single query.
     * @param  \GraphQL\Type\Definition\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 FooFunction($rootValue, array $args, GraphQLContext $context, ResolveInfo $resolveInfo)
    {
        return
            DB::table('...')
              ->where(...)
              ->get();
    }
}

【讨论】:

  • 这对你没有帮助?
【解决方案2】:

Lighthouse 提供像 @hasOne、@hasMany、@belongsTo 这样的指令来防止 N+1 问题。您需要做的就是使用它们。

https://lighthouse-php.com/master/eloquent/relationships.html#avoiding-the-n-1-performance-problem

【讨论】:

  • 是的,但是业务逻辑会去哪里呢?我的理解是,自定义解析器适用于您想要使用业务逻辑的时候。我无法弄清楚使用内置解析器的业务逻辑在哪里。
【解决方案3】:

答案有点晚,但问题是我没有完全理解 graphql 模型。自定义解析器纯粹需要发回正确类型的模型,以便架构可以理解它。我的解析器没有返回正确的类型。

【讨论】:

    猜你喜欢
    • 2019-11-04
    • 2020-03-31
    • 2021-10-22
    • 1970-01-01
    • 2019-11-23
    • 2020-05-01
    • 2020-01-18
    • 2023-02-13
    • 2020-10-22
    相关资源
    最近更新 更多