ورژن بندی api ها در لاراول
یکی از بحث های مهم در توسعه وب سایت ها ورژن بندی api های اون هست .این موضوع به چه دلیل مهمه ؟ بزارید مثال بزنم .
شما api برای دریافت لیست کاربران نوشتید که مثلا دارای ویژگی های زیر هست و در یک اپلیکیشن موبایل استفاده شده:
https://www.ahmadn.com/api/users
[{ "name": "ahmad", "email": "[email protected]", "phone": "+989182418250" },{ ....}]
خب تا اینجا همه چی اوکی هست و مشکلی نداریم اما فرض کنید ما بخوایم یک فیلد به این موارد اضافه کنیم . مثلا
[{ "name": "ahmad", "email": "[email protected]", "phone": "+989182418250" "address": "iran" },{ ....}]
خب در سمت اپلکیشن هم فیلد جدید اعمال میشه و کاربران با آپدیت به اون دسترسی پیدا میکنند.اما اینجا یکمشکل بزرگ هست ! اگه کاربری آپدیت نکنه چی ؟ خب با خطا مواجه میشه چون تو نسخه های قبلی اپلیکیشن موبایل فیلد address تعریف نشده.
خب برای حل این مشکل ما میایم از ورژن بندی api ها استفاده میکنیم . کار زیاد پیچیده ای هم نیست یعنی در نهایت باید به شکل زیر باشه :
https://www.ahmadn.com/api/v1/users https://www.ahmadn.com/api/v2/users
در پوشه کنترلرها(app/Http/Controllers) یک فولدر به اسم api و داخل اون مثلا فولدرهای v1,v2, … رو درست میکنیم ( برای Resource هم میتونیم همین کار رو انجام بدیم ). بعد مثل زیر میتونیم api هامونو به کنترلر هاارتباط بدیم :
<?php namespace App\Http\Controllers\Api\V1; use App\Models\User; class UserController { public function getUser(int $idUser) { $user = User::find($idUser); return new \App\Http\Resources\V1\User($user); } }
خب گام بعدی اینه که ورژن فعلی api های سیستم رو مشخص کنیم .برای اینکار داخل فایل config/app.php میایم و کد زیر رو اضافه میکنیم :
/* |------------------------------------------- | Current API Version |------------------------------------------- | That is the default API version of your API (Last version). | The idea is that if there is no version when calling the API, it | will be used this one. */ 'api_latest' => '1',
و بعد یک میدلوار میسازیم و اینجوری تغییرش میدیم :
php artisan make:middleware APIVersion ٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫ ٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫ ٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫ public function handle($request, Closure $next, $guard) { config(['app.api.version' => $guard]); return $next($request); } ٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫ ٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫٫
در فایل app/Http/Kernel.php و ../app/Providers/RouteServiceProvider.php به ترتیب کدهای زیر رو اضافه میکنیم :
protected $routeMiddleware = [ // ... 'api_version' => \App\Http\Middleware\APIversion::class, ];
/** @var string $apiNamespace */ protected $apiNamespace ='App\Http\Controllers\Api';
در فایل routeserviceprovider کدهای قسمت api رو به شکل زیرتغییر میدیم . دو تابع جدید تعریف کردیم و اونار به قسمتboot اضافه کردیم.
public function boot() { $this->configureRateLimiting(); $this->routes(function () { $this->mapApiRoutesv1(); $this->mapApiRoutesv2(); Route::middleware('web') ->namespace($this->namespace) ->group(base_path('routes/web.php')); }); } protected function mapApiRoutesv1() { Route::prefix('api/v1') ->middleware(['api', 'api_version:v1']) ->namespace("$this->apiNamespace\V1") ->group(base_path('routes/api/v1.php')); } protected function mapApiRoutesv2() { Route::prefix('api/v2') ->middleware(['api', 'api_version:v2']) ->namespace("$this->apiNamespace\V2") ->group(base_path('routes/api/v2.php')); }
خب حالابه پوشه routes میریم و یک فولدر جدید به اسم api درست میکنیم و داخل اون فایل های v1.php,v2.php,… ایجادمیشه که روت های api ما هستند.