為什麼要有 轉換格式呢? 有時候可能資料表原本的欄位不想讓請求用戶可以直接看到,不想直接讀出整個資料表的所有欄位,有些沒必要提供的就可以趁這時候把他移除掉喔!
需求
前一天我們做了Model 關聯的設定,這樣就可以在查詢animal 同時關聯出分類,以及利用生日欄位計算年齡,符合常見需求,讓請求者可以直接讀取年齡數值不需要再轉換!
定義統一資料結構
依照需求的要求思考一下要顯示那些資料給請求的用戶
{
"id": 2,
"type": {
"id": 1,
"name": "狗",
"sort": 0
},
"name": "大黑",
"birthday": "2017-01-01",
"age": "2歲8月",
"area": "台北",
"fix": 1,
"description": "非常可愛,非常任命的一隻狗",
"personality": "認養他準沒錯",
"created_at": "2019-08-24 16:55:29",
"updated_at": "2019-08-24 16:55:29"
}
原本
{
"id": 3,
"type_id": 1,
"name": "黑熊",
"birthday": "2017-01-01",
"area": "台北",
"fix": 1,
"description": "黑狗,胸前有白毛!宛如台灣黑熊",
"personality": "非常親人!很可愛~",
"created_at": "2019-08-24 17:05:07",
"updated_at": "2019-08-24 17:05:07"
}
可以看到這兩個差別,原本只會顯示 "type_id": 1
對於請求用戶的使用體驗上並沒有很好,所以要把與type的關聯加上,另外年齡的部分直接計算出來可以省去使用者自行在轉換一次,並且一樣提供生日欄位,讓不符合需求時用戶再自行轉換。
有幾件事需要做
生日轉換年齡
其中 age 參數計算 生日到目前為止的時間,X歲X月。
分類關聯
這個部分必須關聯到types這張資料表,Type 這個物件想要顯示什麼內容呢?!
{
"id": 1,
"name": "狗",
"sort": 0,
},
原本
{
"id": 1,
"name": "狗",
"sort": 0,
"created_at": "2019-09-01 15:10:53",
"updated_at": "2019-09-01 15:10:53"
},
剔除掉新建時間,以及更新時間這些不必要的欄位,這些欄位在後端處理時有個紀錄就可以,使用者請求時就不讓他們特別顯示。
寫程式囉
產生 Resource
本來想要手動製作轉換器,發現我的規劃好像有點超出30天,所以直接來新建 Resource 檔案吧!
php artisan make:resource TypeResource
animal/app/Http/Resources/TypeResource.php
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'sort' => $this->sort
];
}
animal/app/Http/Resources/AnimalResource.php
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class AnimalResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'type' => new TypeResource($this->type),
'name' => $this->name,
'birthday' => $this->birthday,
'age' => $this->age,
'area' => $this->area,
'fix' => $this->fix,
'description' => $this->description,
'personality' => $this->personality,
'created_at' => $this->created_at != null ? $this->created_at->toDateTimeString() : null,
'updated_at' => $this->updated_at != null ? $this->updated_at->toDateTimeString() : null,
];
}
}
animal/app/Animal.php
加入 getAgeAttribute()
use Carbon\Carbon;
/**
* 計算年齡
*
* @param string $value
* @return string
*/
public function getAgeAttribute()
{
$diff = Carbon::now()->diff($this->birthday);
return "{$diff->y}歲{$diff->m}月";
}
這是一個Laravel 方便的功能 https://learnku.com/docs/laravel/5.7/eloquent-mutators/2297#defining-an-accessor
可以再Model寫一個方法,名稱命名為 get某某某Attribute
例如 getAgeAttribute。必須用駝峰式的命名方式,如果我要取得Animal這個物件並想要的到age的值,會訪問這個方法,並依造你的程式回傳對應的值。
接下來修改 Controller 把查詢單一動物的功能,依照下方程式碼修改。
animal/app/Http/Controllers/AnimalController.php
use App\Http\Resources\AnimalResource;
public function show(Animal $animal)
{
return response(new AnimalResource($animal), Response::HTTP_OK);
}
把 $animal 包到 AnimalResource 物件中... 大功告成,內容應該會顯示如下方JSON
{
"id": 2,
"type": {
"id": 1,
"name": "狗",
"sort": 0
},
"name": "大黑",
"birthday": "2017-01-01",
"age": "2歲8月",
"area": "台北",
"fix": 1,
"description": "非常可愛,非常任命的一隻狗",
"personality": "認養他準沒錯",
"created_at": "2019-08-24 16:55:29",
"updated_at": "2019-08-24 16:55:29"
}