如果你想在Laravel中使用GraphQL,Lighthouse是一个不错的选择
我们正在使用Laravel与GraphQL一起部署生产环境的服务器。通过使用Lighthouse库,我们能够轻松搭建它。以下是我们在搭建过程中积累的经验。
结论就是
-
- Laravel + GraphQL は、 Laravel の柔軟性と GraphQL の堅牢性がいい感じにマッチしている
-
- Laravel で GraphQL やるなら、 Lighthouse 良い
- Schema をダンプしてチームでシェアするといい感じになる
在现实世界中应用GraphQL
我认为使用GraphQL的动机有以下几点。
-
- 型安全な Web API を作りたい
-
- 入出力を明確にしたい
- フロントとサーバー間の仕様書を、動いているコードから明確に作りたい
然而,阻碍的是
-
- 既存のサービスのロジックを使いまわしたい
- 徐々に移行したい。三ヶ月かかります、みたいなのはきつい
我认为一种常见的情况是将GraphQL与现有的框架结合起来,并逐步引入它。例如,在新开发的API中选择GraphQL。
在这种情况下,由于开发资源受限,能够轻松地创建GraphQL服务器非常重要。使用像Laravel这样的LL系语言框架的原因之一可能是能够以低学习成本快速进行开发。从团队文化的角度来看,将功能迅速交付给用户可能比花时间准确地完成更为重要,即使有些bug也可以容忍。在这种情况下,如果编写大量GraphQL类型定义会增加工作负担,那么作为团队采用它可能会很困难。
Lighthouse可以在最小的努力下利用类型定义来构建GraphQL服务器。我们来与其他GraphQL库进行比较。
使用Laravel开发时的GraphQL选择
-
- laravel-graphql
graphql-laravel
laravel-graphql から派生したので、使い勝手は大体同じ
Lighthouse
灯塔的特点
和他的两个库相比,它非常简洁,可以像GraphQL一样编写。类似于Node.js的Apollo-Server,很容易进行比较。
型定义很简单
Laravel-GraphQL 可以用以下一种方式进行原意的表达:
拉韦尔-GraphQL
class UserType extends GraphQLType
{
protected $attributes = [
'name' => 'User',
'description' => 'A user'
];
public function fields()
{
return [
'id' => [
'type' => Type::nonNull(Type::int()),
'description' => 'The id of the user'
],
'email' => [
'type' => Type::string(),
'description' => 'The email of user'
],
'posts' => [
'type' => Type::listOf(GraphQL::type('Post')),
'description' => 'The posts of user'
]
];
}
protected function resolveEmailField($root, $args)
{
return strtolower($root->email);
}
}
灯塔
type User {
# The id of the user
id: ID!
# The email of user
email: String
# The posts of user
posts: [Post!] @hasMany
}
你是否注意到了明显的简化?
设计的思路是这样的,即读取和使用GraphQL文件。
顺便提一下,没有针对特定属性(比如 resolveEmailField)的解析器,但似乎可以使用魔法方法来解决。在上面的例子中,可以使用 User#getEmailAttribute 这样的方法。
以下是对原文的中文本地化释义:
可以用GraphQL编写查询定义。
Laravel-GraphQL是一种Laravel框架的插件。
'schemas' => [
'default' => [
'query' => [
'users' => 'App\GraphQL\Query\UsersQuery'
],
'mutation' => [
'updateUserEmail' => 'App\GraphQL\Query\UpdateUserEmailMutation'
]
],
],
灯塔
type Query {
users: [User] @field(resolver: "App\\GraphQL\\User@resolve")
}
type Mutation {
updateUserEmail(email: String): User @field(resolver: "App\\GraphQL\\Query\\UpdateUserEmailMutation")
}
在Laravel-GraphQL中,您有两个选项来配置或使用`GraphQL::addSchema(’users’,…)`门面。而在Lighthouse中,您需要在graphql文件中指定。
个人来说,我觉得配置文件和外观模式有点不同,如果可以的话,我更想用GraphQL来定义。
由于Lighthouse可以加载其他的graphql文件,因此分割变得简单,同时还可以一目了然地知道查询接受什么并返回什么。
在建立关系时,能够避免N+1问题。
GraphQL的关联是一个令人头痛的问题,通常需要解析查询并根据需要进行Eager Loading。我记得目前GraphQL-Rails也是这样,未来可能会进行改进。
在Laravel-GraphQL中也是一样的,这里的文档中提供了实际的代码示例。
$fields = $info->getFieldSelection($depth = 3);
$users = User::query();
foreach ($fields as $field => $keys) {
if ($field === 'profile') {
$users->with('profile');
}
if ($field === 'posts') {
$users->with('posts');
}
}
是的。每次创建查询都要这样做吗?使用GraphQL有什么意义…
灯塔会自动为我们处理这个。只需指定 @hasMany 指令,它会自动解决关系并返回解决了 N+1 问题的查询结果。真厉害。
追踪代码发现似乎使用了Union查询。事实上,我在SQL日志中也看到了同样的情况。
生成 schema.graphql 的动作
Lighthouse 提供了一个名为 php artisan lighthouse:print-schema 的命令,可以使用它输出模式。
使用GraphDoc等工具,将其输出为有活力的HTML文档是一个不错的选择。
-
- https://github.com/2fd/graphdoc
https://2fd.github.io/graphdoc/pokemon/ (デモ)
另外,在 CI 中,通过生成这类文档,并将其存储为 S3 上的静态网站,再与前端工程师共享,你就能够建立起一个很棒的前端环境。
在当前版本的 Laravel-GraphQL 中似乎没有命令来转储 Schema。
开发非常活跃
在这个 laravel-graphql 的问题中,由于近三个月没有更新,大家都倾向于使用 Lighthouse。我也看了这个帖子后进行了迁移(因为项目已经进行到了后期,所以有点困难哈哈)。
到目前为止(2018/08/11),根据Lighthouse的提交时间是在一天前,而且对问题的回复也非常迅速,所以对于未来也可以期待。
例如,对我提交的问题,他们很负责地给予了回复,并表示希望将其采纳。这让我感动不已。
我暂时会保持这个问题的开放,以便讨论如何将政策应用到具体的模型实例上。很想得到更多的反馈/听到更多的应用案例。
由于目前明星数量不是很多,因此可能注目度较低。
【补充说明】
在写这篇文章的8个月后(2019/03/21),仍然很活跃,最近两天还提交了代码并进入了3版本的测试阶段。
经过调查,我发现负责制作的是一家名为Nuwave的美国公司,他们似乎是一家从事Laravel和GraphQL相关委托开发的公司。所以他们能提供高质量的代码、活跃的开发、易于阅读的文档和友善的社区,并不足为奇。
文件非常齐全
laravel-graphql的文档相对而言比较简洁。从文档的意义上来说,只有Readme.md和docs/advanced.md这两篇实质性的文档。
灯塔拥有专门的仓库,非常易读。
-
- https://github.com/nuwave/lighthouse-docs
- https://lighthouse-php.netlify.com/
此外,还有一个名为“如何…”的问题由有志发起,这里汇集了如何应对这种情况的信息。这对我来说非常有帮助。
然而,似乎文件的导入有些滞后,虽然存在一些隐而未见的功能,但感觉并没有在文件中体现出来。
如果想要创建一个自己的 Directive,就需要阅读现有的源代码。不过别担心,因为它们都是写得很易读的,所以并不会太费劲。
总结
虽然一些人可能会感到不适应、抵触或者对这种严格执行的方式有所抵触,但这种方式与 Apollo 和 GraphQL-Ruby 相似,我并不担心。
如果你喜欢简洁的框架或者希望像 PHP 那样定义查询,也许你会更喜欢 laravel-graphql,但是,在使用 Laravel 的时候就会感觉有些束缚……这是有所顾虑的。毕竟它是开源软件。
虽然星级还不够多,但这是一个值得关注的库。
因为我个人非常喜欢Lighthouse,所以我狂赞了它,但如果更多的人能使用它就好了。
如果有需要的话,我会考虑制作一些教程之类的东西。
顺便
如果有人想要使用Laravel + GraphQL进行开发,我可以介绍那些在https://lighthouse-php.com/users/上列出的公司,请告诉我。