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
410
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
GraphQLに入門してみた
第162回PHP勉強会@東京で話す予定の資料です。
chiroruxx
March 27, 2024
More Decks by chiroruxx
See All by chiroruxx
Contextとはなにか
chiroruxx
1
450
初心者エンジニアから中級者エンジニアになるためにオススメの1冊
chiroruxx
0
140
Laravelのパッケージ全部紹介する
chiroruxx
2
150
Gopher のための「自由な話し合い」ワークショップ
chiroruxx
0
54
PHPをGoで動かす
chiroruxx
0
110
Goを使ってTDDを体験しよう!
chiroruxx
1
1.2k
今ならできる!PhpStormプラグイン開発
chiroruxx
0
120
Go Connectへの想い
chiroruxx
0
240
eBPF with PHPをさわる
chiroruxx
0
200
Other Decks in Technology
See All in Technology
APIセキュリティを組織で実現するには~注力する点と設計・実装に入れたい対策~
riiimparm
3
920
Level Up Your CDK DX: 5 Tools I’ve Been Building
gotok365
2
180
Kiro Crewしか勝たん!?
miu_crescent
PRO
0
170
Bet AI Day 2026丨バクラク Autopilot、業務システムの再設計
layerx
PRO
2
1k
[DroidKaigi 2026] Making UI specifications visible: Android UI development in the AI agent era supported by Compose Screenshot Testing and galleries
syarihu
0
520
データエンジニアリングワークショップ:Auto LoaderとSparkで学ぶデータパイプライン構築
databricksjapan
PRO
0
140
少人数データチームのDevin活用実践事例
runandy16
2
430
どんな手を使っても絶対間に合わせるスケジューラ
asari194617
0
1.5k
深夜のクラウド懺悔室 1:29:300 or 1:0:0
kazzpapa3
0
100
Does an AI Watermark Survive Translation?
machinetranslation
0
520
Self Healing Rollouts: Automating Production Fixes with Agentic AI
kdubois
0
140
ブラウザアプリの継続的パフォーマンスモニタリング (序) / Continuous Browser Application Performance Monitoring; Act 1
moznion
0
100
Featured
See All Featured
The SEO Collaboration Effect
kristinabergwall1
1
550
Faster Mobile Websites
deanohume
310
32k
Building a A Zero-Code AI SEO Workflow
portentint
PRO
0
700
Color Theory Basics | Prateek | Gurzu
gurzu
0
450
Hiding What from Whom? A Critical Review of the History of Programming languages for Music
tomoyanonymous
3
1.2k
Paper Plane
katiecoart
PRO
2
53k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
23k
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
69
65k
Java REST API Framework Comparison - PWX 2021
mraible
34
9.7k
Measuring Dark Social's Impact On Conversion and Attribution
stephenakadiri
2
270
Context Engineering - Making Every Token Count
addyosmani
9
1.1k
Agile Actions for Facilitating Distributed Teams - ADO2019
mkilby
0
270
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を使うことで解消できる