引言
我們一直在講,通過路由傳達到控制器,處理好資料並渲染到檢視,但是對於現代的應用,
前後端分離的情況下,後端寫個介面就完事兒了。
本期為大家說一說用laravel寫restful風格的API,看看能有多簡單。
以路由開端
寫API介面,與傳統的渲染前端模板頁面有什麼區別?少了檢視,只需要準備好資料,
並按照規則格式化,返回就可以了。
laravel預設的api介面路由在 routes/api.php 檔案內定義,預設的情況下預定義了一個資源型別的api介面,程式碼如下:
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
呼叫了 auth:api 中介軟體用於驗證使用者的授權,如果授權通過,宣告的get方法獲取使用者的資訊,並返回 User 模型。這在之前的章節是很常見的操作,我們不做贅述了。
那麼這個路由檔案,是什麼時候載入上去的呢?在檔案 app/Providers/RouteServiceProvider.php 內,看這樣一段:
protected function mapApiRoutes()
{
Route::prefix('api')
->middleware('api')
->namespace($this->namespace)
->group(base_path('routes/api.php'));
}
該服務提供者宣告路由使用 api 字元字首,並呼叫 api 中介軟體,該中介軟體定義在 app/Http/Kernel.php 檔案內:
protected $middlewareGroups = [
'api' => [
'throttle:60,1',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
至於名稱空間 $this->namespace 一般返回 App\Http\Controllers,我們為了區分API與其他應用,在目錄 app/Http/Controller 下建立 API 目錄,用於儲存所有API相關的控制器。
那麼上述的 RouteServiceProvider.php 檔案內 mapApiRoutes 方法內的 namespace 需要這樣寫:
->namespace($this->namespace . '\API')
仍然以 Event 模型作為示例,在 routes/api.php 檔案內宣告一個資源型別的路由:
Route::resource('/events', 'API\EventsController');
注意名稱空間上多出來的字首 API\ ,這說明我們是把 EventController 檔案放在了 API 目錄下。
使用者許可權
讓我們把目光還聚焦在系統預設宣告的那條路由:
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
這一段定義了我們使用何種方式認證使用者的身份。預設的驅動 token 定義在框架檔案 laravel/framework/src/Illuminate/Auth/TokenGuard.php 內。長話短說,預設構造類傳入的欄位如下:
'guards' => [
'api' => [
'driver' => 'token',
'provider' => 'users',
'hash' => false,
],
],
這一段定義了我們使用何種方式認證使用者的身份。預設的驅動 token 定義在框架檔案 laravel/framework/src/Illuminate/Auth/TokenGuard.php 內。長話短說,預設構造類傳入的欄位如下:
UserProvider $provider,
Request $request,
$inputKey = 'api_token',
$storageKey = 'api_token',
$hash = false
簡單說,就是使用 users 表的 api_token 欄位使用者鑑權。那麼預設我們 users 表顯然缺少一個這樣的欄位,現在使用遷移檔案補上:
php artisan make:migration add_api_token_field_to_users_table --table=users
首先是遷移方法 up 函式:
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->string('api_token', 60)->unique();
});
}
還有回滾使用的 down 方法:
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('api_token');
});
}
這些都是常規操作,我們在之前的章節,使用了N多次了。執行指令遷移資料庫:
php artisan migrate
看看效果
準備好了路由,而且路由內宣告瞭一個get方法返回使用者模型資料。也準備好了資料庫表欄位 api_token。我們在資料庫表內找到一個使用者資料,把api_token值設定為 1234,用於測試。
現在在瀏覽器內請求類似如下的url地址:
http://www.example.com/api/user?api_token=1234
如無異常,順利會輸出一個 json 字串,
{
"id":1,
"provider":null,
"provider_id":null,
"first_name":"Tom",
"last_name":"Hanks",
"email":"tom@admin.com",
"city":"",
"state_id":null,
"zip":"43016",
"lat":null,"lng":null,
"timezone":"America\/New_York",
"title":"Laravel Developer",
"created_at":"2020-10-14 17:46:19",
"updated_at":"2020-10-14 17:46:20",
"last_login_at":null,
"is_admin":0,
"api_token":"1234"
}
這個json格式的資料是怎麼來的呢?是在路由內,$request->user() 方法返回的User模型,使用 toArray() 格式化方法獲得的。為了演示,很多欄位與實際可能有所出入。
特別需要注意的是,關鍵的密碼欄位,以及 token 欄位,是預設隱藏的,這得益於 User 模型內 $hiden 屬性的定義:
protected $hidden = [
'password', 'remember_token',
];
這些欄位都對對外不公開訪問。
寫在最後
本文介紹瞭如何宣告api地址,已經解釋了api從中介軟體到路由的由來,明白了api授權的方式,可以為我們更靈活地定製授權方式提供便利。這在laravel內都是可插拔的,替換為我們的邏輯程式碼就可以愉快工作了。
Happy coding :-)
我是@程式設計師小助手,專注程式設計知識,圈子動態的IT領域原創作者
本作品採用《CC 協議》,轉載必須註明作者和本文連結