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
340
GraphQLに入門してみた
第162回PHP勉強会@東京で話す予定の資料です。
chiroruxx
March 27, 2024
Tweet
Share
More Decks by chiroruxx
See All by chiroruxx
eBPF with PHPをさわる
chiroruxx
0
110
sl完全に理解したつもり
chiroruxx
0
95
命名をリントする
chiroruxx
1
760
良い命名かを調べるリンターを作った + α
chiroruxx
0
99
GoLandを布教する会
chiroruxx
0
33
PHPはいつから死んでいるかの調査
chiroruxx
3
640
元phperから見たGoの良いところ
chiroruxx
0
87
Go Connectへの想い
chiroruxx
0
470
ドキュメンテーションコメント再入門
chiroruxx
0
280
Other Decks in Technology
See All in Technology
Standard Schema: スキーマライブラリの統一企画とは何か
nozomuikuta
1
440
Okayama WordPress Meetup #12 | そのバックアップ、本当に復元できますか? リストアやってみた!
takeshifurusato
0
100
Swiftは最高だよの話
yuukiw00w
0
230
Redmineの意外と知らない便利機能 (Redmine 6.0対応版)
vividtone
0
690
AIに実況させる / AI Streamer
motemen
2
1.2k
Cloud Run を解剖して コンテナ監視を考える / Breaking Down Cloud Run to Rethink Container Monitoring
aoto
PRO
0
110
Things you never dared to ask about LLMs — v2
glaforge
1
400
人とAIとの共創を夢見た2か月 #共創AIミートアップ / Co-Creation with Keito-chan
kondoyuko
0
440
Oracle Cloud Infrastructure:2025年5月度サービス・アップデート
oracle4engineer
PRO
0
250
VueUseから学ぶ実践TypeScript #TSKaigi #TSKaigi2025
bengo4com
3
5.3k
研究開発部メンバーの働き⽅ / Sansan R&D Profile
sansan33
PRO
3
17k
Oracle Base Database Service 技術詳細
oracle4engineer
PRO
8
65k
Featured
See All Featured
Intergalactic Javascript Robots from Outer Space
tanoku
271
27k
What’s in a name? Adding method to the madness
productmarketing
PRO
22
3.5k
A designer walks into a library…
pauljervisheath
205
24k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
45
7.3k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
30
2.1k
Learning to Love Humans: Emotional Interface Design
aarron
273
40k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
31
1.2k
Navigating Team Friction
lara
185
15k
Product Roadmaps are Hard
iamctodd
PRO
53
11k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
667
120k
Code Review Best Practice
trishagee
68
18k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
1
58
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を使うことで解消できる