Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
GraphQLに入門してみた
Search
chiroruxx
March 27, 2024
Technology
2
370
GraphQLに入門してみた
第162回PHP勉強会@東京で話す予定の資料です。
chiroruxx
March 27, 2024
Tweet
Share
More Decks by chiroruxx
See All by chiroruxx
Gopher のための「自由な話し合い」ワークショップ
chiroruxx
0
17
PHPをGoで動かす
chiroruxx
0
70
Goを使ってTDDを体験しよう!
chiroruxx
1
780
今ならできる!PhpStormプラグイン開発
chiroruxx
0
69
Go Connectへの想い
chiroruxx
0
200
eBPF with PHPをさわる
chiroruxx
0
150
sl完全に理解したつもり
chiroruxx
0
140
命名をリントする
chiroruxx
1
940
良い命名かを調べるリンターを作った + α
chiroruxx
0
140
Other Decks in Technology
See All in Technology
Introduction to Sansan Meishi Maker Development Engineer
sansan33
PRO
0
330
ALB「証明書上限問題」からの脱却
nishiokashinji
0
220
SwiftDataを覗き見る
akidon0000
0
280
形式手法特論:コンパイラの「正しさ」は証明できるか? #burikaigi / BuriKaigi 2026
ytaka23
17
6.3k
自己管理型チームと個人のセルフマネジメント 〜モチベーション編〜
kakehashi
PRO
5
3.1k
Node vs Deno vs Bun 〜推しランタイムを見つけよう〜
kamekyame
1
530
Introduction to Bill One Development Engineer
sansan33
PRO
0
350
迷わない!AI×MCP連携のリファレンスアーキテクチャ完全ガイド
cdataj
0
580
みんなでAI上手ピーポーになろう! / Let’s All Get AI-Savvy!
kaminashi
0
150
旬のブリと旬の技術で楽しむ AI エージェント設計開発レシピ
chack411
1
290
クラウドセキュリティの進化 — AWSの20年を振り返る
kei4eva4
0
130
スクラムマスターが スクラムチームに入って取り組む5つのこと - スクラムガイドには書いてないけど入った当初から取り組んでおきたい大切なこと -
scrummasudar
3
2.2k
Featured
See All Featured
Rails Girls Zürich Keynote
gr2m
95
14k
Imperfection Machines: The Place of Print at Facebook
scottboms
269
13k
AI Search: Where Are We & What Can We Do About It?
aleyda
0
6.8k
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
160
The #1 spot is gone: here's how to win anyway
tamaranovitovic
1
890
Kristin Tynski - Automating Marketing Tasks With AI
techseoconnect
PRO
0
120
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
How to Think Like a Performance Engineer
csswizardry
28
2.4k
Ten Tips & Tricks for a 🌱 transition
stuffmc
0
51
A Tale of Four Properties
chriscoyier
162
24k
The AI Search Optimization Roadmap by Aleyda Solis
aleyda
1
5.1k
Navigating Team Friction
lara
191
16k
Transcript
GraphQL に 入門 してみた 2024/03/27 第162回 PHP勉強会@東京
⾃⼰紹介 ▪ ちひろ ▪ Twitter: @chiroruxxxx ▪ 会社: 株式会社モリサワ
話すこと/話さないこと ▪ 話すこと – 自分がGraphQL in PHP の勉強をして学んだこと – サンプルコードは
chiroruxx/lighthouse-sample に ▪ 話さないこと – フロントエンド寄りの話 – 取得以外の処理
GraphQL
GraphQLの特徴 ▪ クライアントが欲しい情報をクエリで送り、サーバがその情報を返す – RESTful API と比べてリクエスト回数を減らせる – 使用しないデータを取得・生成する必要がない ▪
HTTPメソッドは基本的にPOSTのみ使用 ▪ HTTPステータスコードは基本的に200のみ使用 ▪ エンドポイントは基本的に1つのみ使用
SELECT id, name FROM users WHERE id = 1; エンジニア
SQL データベース query { user(id: 1){ id , name, } } ブラウザ GraphQL Webサーバ
リクエストとレスポンス query { user(id: 1){ id, name, } } {
"data" : { "user" : { "id" : "1", "name" : "Taro” } } }
リクエストとレスポンス query { user(id: 1) { id, name, post(id: 2)
{ id, title, } } } { "data" : { "user" : { "id" : "1", "name" : "Taro", "post" : { "id" : "2", "title" : "PHP勉強会に参加したよ" } } } }
バックエンドの関心事 ▪ リクエストボディからクエリを解釈する ▪ 必要なデータを取得・生成してレスポンスを返す ライブラリを使う エンジニアが作る
lighthouse ▪ Laravelのプラグインのひとつ ▪ Eloquentと密結合で使うことでほぼコードを書かなくて済む – 今回は理解のためにあえて使用しない
今回考える題材 ▪ ブログをつくる – ユーザが複数の投稿を持つ – 投稿が複数のコメントを持つ ▪ 一度に全部つくらずにインクリメンタルにつくる ▪
lighthouseの設定方法は省略
ユーザを取得する
クエリ query { user(id: 1) { id, name, } }
メインのコード ▪ App¥GraphQL¥Queries¥User を作成する /** @param array{"id": string} $args */
public function __invoke(null $_, array $args): GraphQLUser { $id = (int)$args['id'] ?? 0; return $this->service->findUser($id); } クエリの引数 (id: 1) DBからデータを取って インスタンスを返す
GraphQLUser final readonly class User { public function __construct( public
int $id, public string $name, public string $email, ) { } }
かんたん!!
ユーザの投稿を取得する
クエリ query { user(id: 1) { id, name, posts {
id, title, content, } } } posts { id, title, content, }
元のコード /** @param array{"id": string} $args */ public function __invoke(null
$_, array $args): GraphQLUser { $id = (int)$args['id'] ?? 0; return $this->service->findUser($id); } postもJoinして 返せばよい・・︖
DBからの取り方 query { user(id: 1) { id, name, } }
query { user(id: 1) { id, name, posts { id, title, content, } } } postsテーブルから 取る必要がない postsテーブルからも 取る必要がある クエリによってアクセスする テーブルが変わる Fields の機能を使う
Fields ▪ 返り値のインスンタンスで追加の属性を取得するロジックを設定できる ▪ そのデータが必要な時には呼ばれ、必要ない時には呼ばれない ▪ App¥GraphQL¥Types¥User¥Posts クラスを作成してそこに書く
Fields public function __invoke(User $user): Collection { return $this->userService->getUserPosts($user); }
最初に書いた処理で 取得したユーザ Where(’user_id’, $user->id) でデータを取ってくる
ユーザの投稿のコメントを取得する
クエリ query { user(id: 1) { id, name, posts {
id, title, content, comments { id, title, } } } } comments { id, title, }
メインのロジック ▪ 先ほどと同じように Fields を使えば良い? ▪ App¥GraphQL¥Types¥Post¥Comments public function __invoke(Post
$post): Collection { return $this->service->getComments($post); }
ログを見てみると? データの数だけ SQLが発⾏されている (N+1問題)
ロジックの流れ 1. ユーザを取得する 2. ユーザの投稿を一括で取得する(投稿A, 投稿B, 投稿C) 3. 投稿Aのコメントを一括で取得する 4.
投稿Bのコメントを一括で取得する 5. 投稿Cのコメントを一括で取得する 投稿の数だけ実⾏される ▪ コメントの取得を遅延させて一括で取る必要がある – BatchLoaderを使う
元のコード public function __invoke(Post $post): Collection { return $this->service->getComments($post); }
BatchLoader
BatchLoader public function load(Post $post): Deferred { $this->posts->put($post->id, $post); return
new Deferred(function () use ($post): Collection { if (!$this->hasResolved) { $this->resolve(); } return $this->results[$post->id]; }); } WhereIn(’post_id’, $this->posts->pluck(‘id’)) で⼀括取得する
ログ N+1問題が解消された︕
まとめ
まとめ ▪ GraphQLはクライアントが欲しい情報をクエリで送り、サーバがその情報を返す ▪ PHPでGraphQLを使用するにはlighthouseが便利 ▪ クエリに応じて必要な情報だけを取得する ▪ ただし、N+1問題が発生しやすい ▪
BatchLoaderを使うことで解消できる