$30 off During Our Annual Pro Sale. View Details »
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
13
PHPをGoで動かす
chiroruxx
0
67
Goを使ってTDDを体験しよう!
chiroruxx
1
730
今ならできる!PhpStormプラグイン開発
chiroruxx
0
63
Go Connectへの想い
chiroruxx
0
190
eBPF with PHPをさわる
chiroruxx
0
140
sl完全に理解したつもり
chiroruxx
0
130
命名をリントする
chiroruxx
1
920
良い命名かを調べるリンターを作った + α
chiroruxx
0
140
Other Decks in Technology
See All in Technology
S3を正しく理解するための内部構造の読解
nrinetcom
PRO
3
240
日本の AI 開発と世界の潮流 / GenAI Development in Japan
hariby
1
200
なぜ あなたはそんなに re:Invent に行くのか?
miu_crescent
PRO
0
130
MySQLとPostgreSQLのコレーション / Collation of MySQL and PostgreSQL
tmtms
1
1.1k
AgentCore BrowserとClaude Codeスキルを活用した 『初手AI』を実現する業務自動化AIエージェント基盤
ruzia
7
1k
2025-12-18_AI駆動開発推進プロジェクト運営について / AIDD-Promotion project management
yayoi_dd
0
150
SREが取り組むデプロイ高速化 ─ Docker Buildを最適化した話
capytan
0
120
Snowflake導入から1年、LayerXのデータ活用の現在 / One Year into Snowflake: How LayerX Uses Data Today
civitaspo
0
2.2k
ExpoのインダストリーブースでみたAWSが見せる製造業の未来
hamadakoji
0
190
【U/Day Tokyo 2025】Cygames流 最新スマートフォンゲームの技術設計 〜『Shadowverse: Worlds Beyond』におけるアーキテクチャ再設計の挑戦~
cygames
PRO
2
1.3k
Bedrock AgentCore Memoryの新機能 (Episode) を試してみた / try Bedrock AgentCore Memory Episodic functionarity
hoshi7_n
2
1.6k
SREには開発組織全体で向き合う
koh_naga
0
410
Featured
See All Featured
Principles of Awesome APIs and How to Build Them.
keavy
127
17k
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
Intergalactic Javascript Robots from Outer Space
tanoku
273
27k
Why You Should Never Use an ORM
jnunemaker
PRO
61
9.7k
Speed Design
sergeychernyshev
33
1.4k
Crafting Experiences
bethany
0
21
Become a Pro
speakerdeck
PRO
31
5.7k
RailsConf 2023
tenderlove
30
1.3k
The World Runs on Bad Software
bkeepers
PRO
72
12k
DBのスキルで生き残る技術 - AI時代におけるテーブル設計の勘所
soudai
PRO
60
37k
Chasing Engaging Ingredients in Design
codingconduct
0
80
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
51
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を使うことで解消できる