iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 15
3

使用Laravel 8 PHP主流框架打造RESTful API(iT邦幫忙鐵人賽系列書)ISBN:9789864345304

本系列文章已集結成冊與鐵人賽文章差異內容,有以下幾點:

更新至Laravel 8、基礎的PHP重點筆記、加強製作API流程細節、加入程式設計模式,優化、重構程式碼的部分,並且於書籍前面的章節介紹Git。

讓您從製作第一個簡單的API到優化自己的程式碼,分享我的經驗給您,打造自己的最強大腦API,若有興趣的朋友可以參考看看

天瓏網路書局:
https://www.tenlong.com.tw/products/9789864345304


此篇文章同步發於個人部落格


為什麼要有 轉換格式呢? 有時候可能資料表原本的欄位不想讓請求用戶可以直接看到,不想直接讀出整個資料表的所有欄位,有些沒必要提供的就可以趁這時候把他移除掉喔!

需求

前一天我們做了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"
}

上一篇
分類CRUD、模型關聯
下一篇
加入會員認證、註冊帳號
系列文
使用 Laravel 打造 RESTful API30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言