1.5K Views
March 21, 25
スライド概要
PHPerKaigi 2025の発表スライドです。
Slimで挑む!OpenAPI活用による API開発の効率化と品質向上 @PHPerKaigi 2025 荒巻 拓哉
自己紹介 ● ● ● ● 荒巻 拓哉 X: @takaram71 PHPer 6年目 株式会社ラクス
今日お話しすること ● OpenAPIとは? ● OpenAPIをチームへ導入 ○ どんなやり方? ○ 実際どうだった?
今日お話ししないこと ● OpenAPIの書き方、文法 ○ 公式ドキュメント など見てください
OpenAPIとは?
OpenAPIとは ● API仕様を記述するための仕様(フォーマット) ● YAML or JSONで記述 ○ YAMLが多い
OpenAPIとは ● URLのパス ● リクエスト ○ ○ ○ メソッド Content-Type ボディ ● レスポンス ○ ステータスコード ○ Content-Type ○ ボディ など……
OpenAPIのメリット ● 統一されたフォーマット ● Git管理できる ● ドキュメント生成 ● クライアントコードの生成 ● リクエスト/レスポンスのバリデーション etc...
統一されたフォーマット ● 一定の書き方が強制される ○ 設計者間のバラつきが少なく ○ 曖昧な書き方が減る
Git管理できる ● YAML = ただのテキストファイル → Git管理可能 ● Pull Request上でレビュー
ドキュメント生成 Redoc Swagger UI スクリーンショット: ● https://petstore.swagger.io/ ● https://redocly.github.io/redoc/?url=openapi-3-1.yaml
ドキュメント生成 https://github.com/swagger-api/swagger-petstore/blob/a0f12dd24efcf2fd68faa59c371ea5e35a90bbd1/src/main/resources/openapi.yaml より
クライアントコードの生成 ● 仕様に沿ったリクエスト/レスポンスの送受信をするコードを 自動生成 ● OpenAPITools/openapi-generator ○ 対応言語 ■ ActionScript, Ada, Apex, Bash, C, C#, C++, Clojure, Crystal, Dart, Elixir, Elm, Eiffel, Erlang, Go, Groovy, Haskell, Java, Jetbrains HTTP Client, Julia, k6, Kotlin, Lua, N4JS, Nim, Node.js/JavaScript, Objective-C, OCaml, Perl, PHP, PowerShell, Python, R, Ruby, Rust, Scala, Swift, Typescript, XoJo, Zapier
リクエスト/レスポンスのバリデーション ● 記述された仕様を満たすか機械的にチェック ○ 仕様書と実装の乖離を防げる ● 言語・フレームワークごとにライブラリがある
OpenAPIのチームへの導入
OpenAPIを導入しようと思ったきっかけ ● PHPerKaigi 2024での発表 ○ Laravel OpenAPIによる "辛くない" スキーマ駆動開発 ● 「解釈の余地がないものから作り、間違えにくい道具を使う」 ○ OpenAPI仕様 → 解釈の余地が少ない ○ 各種ツールの利用 → 間違えにくい
対象機能 ● 新規開発するサブシステム ○ Slim Framework ● 他のサーバーからHTTP通信を受け付ける 新規開発 HTTP
私のチームでの導入方法 ● YAMLで書いてGitにコミット ● PhpStormで閲覧 ● リクエスト/レスポンスのバリデーション
ドキュメントの閲覧 ● PhpStormで閲覧 ● GitLabで閲覧 ○ ブランチごとにURLで共有できて便利 ○ GitHubに移行してしまい見られなくなった……
ドキュメントの閲覧 ● PhpStormで閲覧 ● GitLabで閲覧 ○ ブランチごとにURLで共有できて便利 ○ GitHubに移行してしまい見られなくなった…… https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/api/openapi/openapi_v2.yaml
リクエスト/レスポンスのバリデーション league/openapi-psr7-validator ● PSR-7のリクエスト/レスポンスオブジェクトを検証 ● SlimはもともとPSR-7準拠 → 導入しやすい ● デメリット:メンテナンス頻度が低い
リクエスト/レスポンスのバリデーション league/openapi-psr7-validator ● バリデーション方法 ○ $validator->validate($request) ○ PSR-15 ミドルウェア
リクエスト/レスポンスのバリデーション league/openapi-psr7-validator ● バリデーション方法 ○ $validator->validate($request) ○ PSR-15 ミドルウェア
リクエスト/レスポンスのバリデーション ● リクエスト ○ openapi-psr7-validator のラッパークラスを作成 ■ バリデーション失敗ならHttpBadRequestException ○ コントローラーから呼び出し
リクエスト/レスポンスのバリデーション
リクエスト/レスポンスのバリデーション ● レスポンス ○ テストコードでバリデーションを実施 ○ 毎リクエスト検証する必要性は薄いと判断
クライアントコード生成は未導入 ● 課題感が大きくなかった ○ エンドポイントの数が多くない ● スモールスタート ○ 一度にいろいろやると混乱が生まれる懸念
実際に導入してみて
導入効果🎉 ● レビューしやすい! ○ PhpStorm上でSwagger UIを見ながらレビュー ○ GitHubのpull request上でコメント ○ 読み方の慣れはやや必要かも
導入効果🎉 ● コード量が減った! ○ 今まで ■ is_int($param) && $param > 0 && … × パラメータ数 ○ 導入後 ■ $validator->validate($request) で一発 ○ あるアクションクラス: 197行 → 80行 (6割減!) ■ パラメータ9つ
導入効果🎉 ● テストでバグを発見できた! ○ レスポンスのフォーマットがOpenAPIの定義と異なるのを すぐ検知 ○ OpenAPIの記述の方が間違っていたケースも
イマイチな点 ● PHPStanとの相性がよくない ○ スキーマ上は整数とわかっていてもPHPStanは認識してくれない ○ @var や assert() が増える
反省点 ● 導入の周知が不十分だった ○ 一部のメンバーで導入の意思決定 ○ 実装担当メンバーが従来の方法で実装を進めてしまった ■ バリデーションロジックを後から変更する手戻り ○ 認識合わせ、サンプル実装の提供などすべき
今後の活用 ● OpenAPIの書き方のミス削減 ○ required の書き忘れなど ○ 対応策 ■ GUIのエディタを利用 ■ Lintツールを導入
今後の活用 ● モックサーバー構築 ○ OpenAPIの定義に合う適当なレスポンスを返してくれる ○ クライアント側の開発時に活用 ○ Prism
まとめ
まとめ ● API開発にOpenAPIを導入してみた ● いくつかメリットを感じられた ○ レビューしやすい ○ コード量削減 ○ テストでのバグ検知
補足
Slimじゃなく(任意のフレームワーク)では使えない? ● PSR-7準拠なら使える ○ 準拠 ■ CakePHP ○ 非準拠 ■ Laravel / Symfony ● symfony/psr-http-message-bridge で変換 ■ CodeIgniter ● そのフレームワーク用のライブラリがある場合も