GraphQL与Laravel Lighthouse:基于关联字段传递变量的类型问题
我正在为本地体育俱乐部开发一款应用,需按运动类别(数据库中为category)提供标准问题(每类5个)并收集答案,之后对答案进行审核批准/驳回。数据库包含questions、answers、assessment三张表,结构如下:
questions - category_id - question_id - question answers - user_id - question_id assessment - user_id - category_id - approved ....
我希望通过传入user_id的GraphQL调用获取该用户提交的所有答案,已定义如下GraphQL类型:
type Assessment { id: ID! user_id: User! @belongsTo category: Category! @belongsTo selfAssessmentQuestions: CategoryAssessmentQuestions! @hasMany selfAssessmentAnswers: CategoryAssessmentAnswers! @hasMany submitted_at: DateTime reviewed_at: DateTime approved: Int! assessor_note: String created_at: DateTime updated_at: DateTime } type CategoryAssessmentQuestions{ active: Int question_id: Int question: String } type CategoryAssessmentAnswers{ id: ID! user_id: User! @belongsTo question (question_id: Int @eq): [CategoryAssessmentQuestions] @hasOne answer: String created_at: DateTime updated_at: DateTime }
目前我可以获取用户X的所有assessment记录,但需要将查询得到的category_id传递给selfAssessmentQuestions节点,以获取对应类别的问题。若使用普通Eloquent查询会让GraphQL失去意义。
核心问题:能否在同一GraphQL类型中,基于其他查询结果进行数据查询?
当然可以在同一GraphQL类型中基于其他字段的结果查询数据,核心是利用自定义字段解析器或关联注解动态传入当前模型参数,以下是三种可行实现方式:
方法1:使用注解绑定当前模型字段(以Laravel Lighthouse为例)
在Assessment类型的selfAssessmentQuestions字段上添加@where注解,直接引用当前assessment的category_id作为查询条件:
type Assessment { # ... 其他字段 selfAssessmentQuestions: [CategoryAssessmentQuestions!]! @hasMany @where(column: "category_id", value: "$category_id") # ... 其他字段 }
$category_id会自动关联当前Assessment实例的category_id属性,查询每个Assessment时,会自动拉取对应类别的问题。
方法2:自定义字段解析器
如果注解方式不够灵活,可编写自定义解析函数实现逻辑:
- 修改GraphQL类型定义,去掉自动关联注解:
type Assessment { # ... 其他字段 selfAssessmentQuestions: [CategoryAssessmentQuestions!]! # ... 其他字段 }
- 编写解析器类(Laravel环境示例):
namespace App\GraphQL\Resolvers; use App\Models\Assessment; use App\Models\Question; use Illuminate\Database\Eloquent\Collection; class AssessmentResolver { public function selfAssessmentQuestions(Assessment $assessment): Collection { return Question::where('category_id', $assessment->category_id)->get(); } }
- 在GraphQL schema中绑定解析器:
extend type Assessment { selfAssessmentQuestions: [CategoryAssessmentQuestions!]! @field(resolver: "App\\GraphQL\\Resolvers\\AssessmentResolver@selfAssessmentQuestions") }
方法3:预先定义Eloquent关联
在Assessment模型中定义关联关系,让GraphQL自动复用:
namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; class Assessment extends Model { // ... 其他模型代码 public function selfAssessmentQuestions(): HasMany { return $this->hasMany(Question::class, 'category_id', 'category_id'); } }
之后在GraphQL类型中保留@hasMany注解即可:
type Assessment { # ... 其他字段 selfAssessmentQuestions: [CategoryAssessmentQuestions!]! @hasMany # ... 其他字段 }
以上三种方法均符合GraphQL设计理念,无需脱离GraphQL上下文编写独立Eloquent查询。
内容的提问来源于stack exchange,提问作者Beertastic

