我的问题涉及如何构建复杂的自定义解析器,以及为什么它们不能很好地与内置解析器配合使用。我找不到任何关于复杂解析器的好例子,而我的真实案例比这个例子还要复杂。
我有以下架构
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代码片段)