Upgrade to Pro — share decks privately, control downloads, hide ads and more …

GraphQLに入門してみた

 GraphQLに入門してみた

第162回PHP勉強会@東京で話す予定の資料です。

chiroruxx

March 27, 2024
Tweet

More Decks by chiroruxx

Other Decks in Technology

Transcript

  1. 話すこと/話さないこと ▪ 話すこと – 自分がGraphQL in PHP の勉強をして学んだこと – サンプルコードは

    chiroruxx/lighthouse-sample に ▪ 話さないこと – フロントエンド寄りの話 – 取得以外の処理
  2. GraphQLの特徴 ▪ クライアントが欲しい情報をクエリで送り、サーバがその情報を返す – RESTful API と比べてリクエスト回数を減らせる – 使用しないデータを取得・生成する必要がない ▪

    HTTPメソッドは基本的にPOSTのみ使用 ▪ HTTPステータスコードは基本的に200のみ使用 ▪ エンドポイントは基本的に1つのみ使用
  3. SELECT id, name FROM users WHERE id = 1; エンジニア

    SQL データベース query { user(id: 1){ id , name, } } ブラウザ GraphQL Webサーバ
  4. リクエストとレスポンス query { user(id: 1){ id, name, } } {

    "data" : { "user" : { "id" : "1", "name" : "Taro” } } }
  5. リクエストとレスポンス query { user(id: 1) { id, name, post(id: 2)

    { id, title, } } } { "data" : { "user" : { "id" : "1", "name" : "Taro", "post" : { "id" : "2", "title" : "PHP勉強会に参加したよ" } } } }
  6. メインのコード ▪ 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からデータを取って インスタンスを返す
  7. GraphQLUser final readonly class User { public function __construct( public

    int $id, public string $name, public string $email, ) { } }
  8. クエリ query { user(id: 1) { id, name, posts {

    id, title, content, } } } posts { id, title, content, }
  9. 元のコード /** @param array{"id": string} $args */ public function __invoke(null

    $_, array $args): GraphQLUser { $id = (int)$args['id'] ?? 0; return $this->service->findUser($id); } postもJoinして 返せばよい・・︖
  10. DBからの取り方 query { user(id: 1) { id, name, } }

    query { user(id: 1) { id, name, posts { id, title, content, } } } postsテーブルから 取る必要がない postsテーブルからも 取る必要がある クエリによってアクセスする テーブルが変わる Fields の機能を使う
  11. Fields public function __invoke(User $user): Collection { return $this->userService->getUserPosts($user); }

    最初に書いた処理で 取得したユーザ Where(’user_id’, $user->id) でデータを取ってくる
  12. クエリ query { user(id: 1) { id, name, posts {

    id, title, content, comments { id, title, } } } } comments { id, title, }
  13. ロジックの流れ 1. ユーザを取得する 2. ユーザの投稿を一括で取得する(投稿A, 投稿B, 投稿C) 3. 投稿Aのコメントを一括で取得する 4.

    投稿Bのコメントを一括で取得する 5. 投稿Cのコメントを一括で取得する 投稿の数だけ実⾏される ▪ コメントの取得を遅延させて一括で取る必要がある – BatchLoaderを使う
  14. 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’)) で⼀括取得する