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
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
chiroruxx
March 27, 2024
Technology
380
2
Share
GraphQLに入門してみた
第162回PHP勉強会@東京で話す予定の資料です。
chiroruxx
March 27, 2024
More Decks by chiroruxx
See All by chiroruxx
初心者エンジニアから中級者エンジニアになるためにオススメの1冊
chiroruxx
0
110
Laravelのパッケージ全部紹介する
chiroruxx
2
110
Gopher のための「自由な話し合い」ワークショップ
chiroruxx
0
32
PHPをGoで動かす
chiroruxx
0
84
Goを使ってTDDを体験しよう!
chiroruxx
1
940
今ならできる!PhpStormプラグイン開発
chiroruxx
0
88
Go Connectへの想い
chiroruxx
0
210
eBPF with PHPをさわる
chiroruxx
0
170
sl完全に理解したつもり
chiroruxx
0
150
Other Decks in Technology
See All in Technology
来期の評価で変えようと思っていること 〜AI時代に変わること・変わらないこと〜
estie
0
140
不確実性と戦いながら見積もりを作成するプロセス/mitsumori-process
hirodragon112
1
180
最大のアウトプット術は問題を作ること
ryoaccount
0
290
ハーネスエンジニアリング×AI適応開発
aictokamiya
3
1.4k
AWSで2番目にリリースされたサービスについてお話しします(諸説あります)
yama3133
0
110
2026-04-02 IBM Bobオンボーディング入門
yutanonaka
0
180
会社紹介資料 / Sansan Company Profile
sansan33
PRO
16
410k
Oracle AI Database@AWS:サービス概要のご紹介
oracle4engineer
PRO
3
2.1k
Data Intelligence Engineering Unit 部門と各ポジション紹介
sansantech
PRO
0
100
Tour of Agent Protocols: MCP, A2A, AG-UI, A2UI with ADK
meteatamel
0
200
Databricks Lakebaseを用いたAIエージェント連携
daiki_akimoto_nttd
0
140
LLMに何を任せ、何を任せないか
cap120
11
7k
Featured
See All Featured
The innovator’s Mindset - Leading Through an Era of Exponential Change - McGill University 2025
jdejongh
PRO
1
140
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
300
Lessons Learnt from Crawling 1000+ Websites
charlesmeaden
PRO
1
1.2k
Music & Morning Musume
bryan
47
7.1k
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
1
220
Practical Orchestrator
shlominoach
191
11k
SEO in 2025: How to Prepare for the Future of Search
ipullrank
3
3.4k
Fashionably flexible responsive web design (full day workshop)
malarkey
408
66k
Building Better People: How to give real-time feedback that sticks.
wjessup
370
20k
Rails Girls Zürich Keynote
gr2m
96
14k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
122
21k
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.6k
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を使うことで解消できる