![](/img/trans.png)
[英]Laravel Lighthouse GraphQL query data from a pivot table that connects three tables
[英]How to create a GraphQL query that returns data from multiple tables/models within one field using Laravel Lighthouse
我正在尝试使用 Laravel 和 Lighthouse 学习 GraphQL 并且有一个问题希望有人可以帮助我。 我有以下五个数据库表,它们也在我的 Laravel 模型中定义:
我想创建一个 GraphQL 端点,它允许我取回一组用户和他们拥有的书籍,在那里我可以将多个表中的数据提取到一个名为“书籍”的子字段中,如下所示:
query {
users {
name
books {
title
issue_number
condition
user_notes
}
}
}
要在 SQL 中完成此操作,使用如下连接很容易:
$users = User::all();
foreach ($users as $user) {
$user['books'] = DB::select('SELECT
book_series.title,
book.issue_number
book_copies.condition,
user_books.notes as user_notes
FROM user_books
JOIN book_copies ON user_books.book_copy_id = book_copies.id
JOIN books ON book_copies.book_id = books.id
JOIN book_series ON books.series_id = book_series.id
WHERE user_books.user_id = ?',[$user['id']])->get();
}
How would I model this in my GraphQL schema file when the object type for "books" is a mashup of properties from four other object types (Book, UserBook, BookCopy, and BookSeries)?
编辑:通过执行如下查询,我能够获得所需的所有数据:
users {
name
userBooks {
user_notes
bookCopy {
condition
book {
issue_number
series {
title
}
}
}
}
}
但是,如您所见,数据被分成多个子对象,不如将所有数据放在一个平面“书籍”object 中那么理想。 如果有人知道我如何将所有数据恢复到一个平面 object 中,我很想知道。
我还注意到,关系的字段名称需要与每个 model 中的 controller 方法名称完全匹配,根据 Laravel 命名约定,它们是驼峰式。 除了我的其他字段与lower_underscore 的数据库列名匹配。 这是一个轻微的挑剔。
好的,在您编辑完您的问题后,我将在此处写下答案,以回答您的新问题。
但是,如您所见,数据被分成多个子对象,不如将所有数据放在一个平面“书籍”object 中那么理想。 如果有人知道我如何将所有数据恢复到一个平面 object 中,我很想知道。
问题是,这种获取数据是 GraphQL 的中心思想。 你有一些类型,这些类型之间可能有一些关系。 因此,您可以获取 object 的任何关系,任何深度,甚至循环。 Lighthouse 为您提供对 eloquent 关系的开箱即用支持与批量加载,避免了 N+1 性能问题。 您还必须记住 - GraphQL 定义中的每个字段(字面意思是每个字段)都在服务器上解析。 因此,每个字段都有一个解析 function。 因此,您可以自由地为特定字段编写自己的解析器。 您实际上可以在 GraphQL 中定义一个符合您最初期望的类型。 然后您可以定义一个根查询字段,例如fetchUsers
,并创建您的自定义字段解析器。 您可以阅读文档,了解它的工作原理以及如何实现: https://lighthouse-php.com/5.2/the-basics/fields.html#hello-world在此字段解析器中,您可以自己制作数据获取,即使不使用任何 Laravel/Eloquent API。 您必须注意的一件事 - 为该字段返回与 GraphQL 中的返回类型相同结构的正确数据类型。
总而言之-您可以选择这样做。 但在我看来,你必须编写更多自己的代码,并用你自己的测试来覆盖它,结果证明你需要做更多的工作。 我认为使用内置指令更简单,例如@find
、 @paginate
、 @all
结合关系指令,它们都包含测试,而不关心实现。
我还注意到,关系的字段名称需要与每个 model 中的 controller 方法名称完全匹配,根据 Laravel 命名约定,它们是驼峰式。
您可能指的是 Model class 中的方法,而不是 controller。 Lighthouse 提供了一个@rename
指令,您可以使用它在 GraphQL 中为您的属性定义不同的名称。 对于关系指令,您可以传递一个relation
参数,该参数将用于获取数据。 所以对于你的例子,你可以使用这样的东西:
type User {
#...
user_books: [Book!]! @hasMany(relation: "userBooks")
}
但是在我们的项目中,我们决定将 snak_case 也用于关系,以保持 GraphQL 干净,并使用一致的命名约定和更少的工作量
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.