Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Laravel で API バージョニングを実装するなら
Search
Shohei Okada
September 26, 2018
Programming
83
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Laravel で API バージョニングを実装するなら
2018-09-26 開催の「第130回 PHP勉強会@東京」におけるLT資料です
https://phpstudy.doorkeeper.jp/events/79982
Shohei Okada
September 26, 2018
More Decks by Shohei Okada
See All by Shohei Okada
Symfony + NelmioApiDocBundle を使った スキーマ駆動開発 / Schema Driven Development with NelmioApiDocBundle
okashoi
0
410
たった 1 枚の PHP ファイルで実装する MCP サーバ / MCP Server with Vanilla PHP
okashoi
1
1.2k
どうして手を動かすよりもチーム内のコードレビューを優先するべきなのか
okashoi
3
2.4k
パスワードのハッシュ、ソルトってなに? - What is hash and salt for password?
okashoi
3
460
設計の考え方 - インターフェースと腐敗防止層編 #phpconfuk / Interface and Anti Corruption Layer
okashoi
11
6.7k
"config" ってなんだ? / What is "config"?
okashoi
0
2k
ファイル先頭の use の意味、説明できますか? 〜PHP の namespace と autoloading の関係を正しく理解しよう〜 / namespace and autoloading in php
okashoi
4
2.3k
MySQL のインデックスの種類をおさらいしよう! / overviewing indexes in MySQL
okashoi
0
1.5k
PHP における静的解析(あるいはそもそも静的解析とは) / #phpcondo_yasai static analysis for PHP
okashoi
1
1.6k
Other Decks in Programming
See All in Programming
なぜCTOを降りてFDEを選んだのか?〜なぜプロダクト企業がFDEで顧客の現場に踏み込むのか〜
gonta
1
220
golang-bob.pdf
iwatsukayura
0
130
JIS keyboard support in Omarchy
lef237
0
130
最近”作らせてる” ローカルAIアプリの話
akit37
0
480
FactoryBotをやめればRSpecは速くなるのか?
yuta_onishi_97
0
650
Simple Storage Service(S3) is not simple
iwatsukayura
0
290
RAG の “R” を Swift で覗いてみる 〜「意味から探す」検索の仕組み〜
nao_randd
0
170
ジョジョの世界をXRで再現する
mofurune
0
170
Agentic Software Factoryに、すごく賢いIF文を。 / super smart IF statement into the Agentic Software Factory.
rkaga
8
2.2k
S3 TablesのIcebergデータに、AIエージェントからアクセスしてみた / 20261016developersio2026joetsu-accessing-iceberg-in-s3tables-via-agent
kasacchiful
PRO
0
160
動作中のプログラムの中身をリアルタイムに覗く / Realtime Debugger for CSharp with Roslyn
prota
1
1.9k
Railsバージョンを4倍にした話
optim
0
440
Featured
See All Featured
The B2B funnel & how to create a winning content strategy
katarinadahlin
PRO
1
570
Data-driven link building: lessons from a $708K investment (BrightonSEO talk)
szymonslowik
1
1.4k
Making Projects Easy
brettharned
120
6.8k
GraphQLとの向き合い方2022年版
quramy
50
15k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
203
77k
Done Done
chrislema
187
17k
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
1k
Ecommerce SEO: The Keys for Success Now & Beyond - #SERPConf2024
aleyda
1
2.2k
Designing for Performance
lara
612
70k
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
69
67k
Intergalactic Javascript Robots from Outer Space
tanoku
273
28k
Unsuck your backbone
ammeep
672
58k
Transcript
API バージョニング を Laravel で実装するなら 第130回 PHP勉強会@東京
岡田 正平(おかだ しょうへい)@okashoi • 株式会社ウィルゲート 2015年新卒入社 • 開発室 ソリューションユニット 所属
• PHP, Laravel, Vue.js 2 自己紹介 Slides:
クライアントに対し、古い形式でのアクセス方法を提供しつづける 例)Google Maps Embed API https://www.google.com/maps/embed/v1/place?q=...&key=... 新しいアクセス方法・レスポンス形式などは v2, v3… としていく
※他にもメディアタイプでバージョンを指定する方法などがある 3 API バージョニング
クライアントに対し、古い形式でのアクセス方法を提供しつづける 例)Google Maps Embed API https://www.google.com/maps/embed/v1/place?q=...&key=... 新しいアクセス方法・レスポンス形式などは v2, v3… としていく
※他にもメディアタイプでバージョンを指定する方法などがある 4 API バージョニング このスライドではいったん この方法で考えます
愚直に考えるとこう routes/api.php 5 Laravel でどう実装する?① Route::get('v1/posts', 'V1/PostController@index'); Route::get('v2/posts', 'V2/PostController@index');
愚直に考えるとこう routes/api.php 6 Laravel でどう実装する?① Route::get('v1/posts', 'V1/PostController@index'); Route::get('v2/posts', 'V2/PostController@index'); バージョンごとに
異なる Controller 明示的に指定
たしかに実現できてるけど…… • 新しいバージョンが増えるたびに、全てを追記するの? ➢ バージョンを扱う部分は仕組み化したい • コントローラを分割してしまうとコピペが横行するおそれアリ ➢ コントローラ内の条件分岐にしたい 7
Laravel でどう実装する?①
8 Laravel でどう実装する?① 参考)http://kenn.hatenablog.com/entry/2014/03/06/105249
改善案:ルーティングパラメータとして渡す 9 Laravel でどう実装する?② Route::get('{version}/posts', 'PostController@index') ->where('version', 'v[1-9][0-9]*'); routes/api.php public
function index(string $versionString, Request $request) { // 'v1' => 1 のように int 値に変換 $version = (int)substr($versionString, 1); if ($version === 1) { // v1 の処理 } // ... 以下略 } apps/MyApp/Application/Http/Controllers/PostConroller.php
改善案:ルーティングパラメータとして渡す 10 Laravel でどう実装する?② Route::get('{version}/posts', 'PostController@index') ->where('version', 'v[1-9][0-9]*'); routes/api.php public
function index(string $versionString, Request $request) { // 'v1' => 1 のように int 値に変換 $version = (int)substr($versionString, 1); if ($version === 1) { // v1 の処理 } // ... 以下略 } apps/MyApp/Application/Http/Controllers/PostConroller.php
改善案:ルーティングパラメータとして渡す 11 Laravel でどう実装する?② Route::get('{version}/posts', 'PostController@index') ->where('version', 'v[1-9][0-9]*'); routes/api.php public
function index(string $versionString, Request $request) { // 'v1' => 1 のように int 値に変換 $version = (int)substr($versionString, 1); if ($version === 1) { // v1 の処理 } // ... 以下略 } apps/MyApp/Application/Http/Controllers/PostConroller.php パターン指定による制限
改善案:ルーティングパラメータとして渡す 12 Laravel でどう実装する?② Route::get('{version}/posts', 'PostController@index') ->where('version', 'v[1-9][0-9]*'); routes/api.php public
function index(string $versionString, Request $request) { // 'v1' => 1 のように int 値に変換 $version = (int)substr($versionString, 1); if ($version === 1) { // v1 の処理 } // ... 以下略 } apps/MyApp/Application/Http/Controllers/PostConroller.php
①の問題点は解決できたものの、欲を言うなら • 毎 action で ←これやるの? ➢ 勝手に変換されていて欲しい • による制限が
に対してできない ➢ パターン指定は一箇所だけにしたい 13 Laravel でどう実装する?② $version = (int)substr($versionString, 1); ->where() Route::group() // できそうでできない Route::group(['prefix' => '{version}'], function () { Route::get('posts', 'PostController@index'); Route::get('users', 'UserController@index'); })->where('version', 'v[1-9][0-9]*');
None
アイディア:Explicit Route Model Binding を使う 15 Laravel でどう実装する?③ カスタマイズロジックを用いれば Eloquent
ORM 以外も Bind できる
1. API バージョンを表現するクラス (Value Object)を作る 2. RouteServiceProvider で Binding を(ついでに
pattern も)登録 3. Controller で利用する 16 Laravel でどう実装する?③
1. API バージョンを表現するクラス (Value Object)を作る 2. RouteServiceProvider で Binding を(ついでに
pattern も)登録 3. Controller で利用する 17 Laravel でどう実装する?③ class ApiVersion { /** * @var int */ protected $value; /** * @param string $versionString */ public function __construct(string $versionString) { $this->value = (int)substr($versionString, 1); } /** * @return int */ public function value(): int { return $this->value; } /** * @param int $number * @return bool */ public function is(int $number): bool { return $this->value === $number; } }
1. API バージョンを表現するクラス (Value Object)を作る 2. RouteServiceProvider で Binding を(ついでに
pattern も)登録 3. Controller で利用する 18 Laravel でどう実装する?③ public function boot(): void { Route::pattern('version', 'v[1-9][0-9]*'); parent::boot(); Route::bind('version', function ($versionString, $route) { return new ApiVersionValue($versionString); }); } tips: は より前 は より後 でないと正しく動かない Route::pattern() parent::boot() Route::bind() parent::boot()
1. API バージョンを表現するクラス (Value Object)を作る 2. RouteServiceProvider で Binding を(ついでに
pattern も)登録 3. Controller で利用する 19 Laravel でどう実装する?③ Route::get('{version}/posts', 'PostController@index'); public function index(ApiVersion $version, R... { // 特定のバージョンかどうか調べるには // $version->is() を使用 if ($version->is(1)) { // v1 の処理 } // バージョンの値を得たければ // $version->value() を使用 if ($version->value() <= 3) { // v2, v3 の処理 } // 以下略 } ↓
• Explicit Route Model Binding は Model 以外にも使い道がある! • API
バージョンを Value Object にするは良い工夫だと思う(自画自賛) • Application Layer の Value Object になる(特殊な例?) • (余談)そもそも API バージョニングって難しい 20 所感など
• 本当にその API にバージョンニングいる? • SSKDs (Small Set of Known
Developers) 向けならいらない? • c.f.) LSUDs (Large Set of Unknown Developers) • 後から足すことになるくらいなら、当面 v1 であってもひとまず…… • どのタイミングでバージョンを変える? • 後方互換が保てなくなったら?時間(1 年ごとなど)で区切る? • エンドポイント単位で更新?API 全体で更新? • バージョン指定なしを許容するか?許容する場合の挙動はどうするか? 21 余談:そもそも API バージョニング難しい問題 などなど……