iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 18
1

REST是種軟體建構風格,常見限制如下:

  • Uniform interface:系統中的資源應有單一邏輯性的URI,提供取得資料的方法。
  • Client–server:服務器和客戶端可獨立替換和開發
  • Stateless:伺服器上不會保留有任何客戶的http請求。若想保留,用戶需先登錄並實作驗證、後續請求需包含驗證
  • Cacheable:在適用資源上提供快取,提高可擴展性和性能
  • Layered system:系統架構分層,例如A伺服器存取、B伺服器驗證身份等。用戶端不會直接知道它連結哪台伺服器。

而這些拘限,讓API架構具備高性能、可擴展、通用性、簡潔、可修改、可擴展等特性。

兩天前的文章有提到如何去create新增一筆資料,這篇會繼續把read、update、delete的部分提完。

Read

預設作法
關於讀取資料的部分,預設有兩個action

Http Verb URI Action
GET /userWater index
GET /userWater/{userWater_id} show

如果不做任何額外設定的話,index預設要列出所有資料,show則依據index裡頭資料回傳的id,提供該id對應的內容

/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
    return response()->json(['success' => true , 'message' =>"" , 'data'=>userWater::all() ],200);
}

/**
* Display the specified resource.
*
* @param \App\userWater $userWater
* @return \Illuminate\Http\Response
*/
public function show(userWater $userWater)
{
    return response()->json(['success' => true , 'message' =>"" , 'data'=>$userWater ],200);
}

個人習慣
預設方法沒有針對單一用戶提供resource的action,因此個人會另外建立一個透過user id取得個人資訊的action,不會直接覆蓋預設的。

   public function waterUser($id)
    {
        $id = intval($id);
        $userP = userWater::where('user_id','=',$id)->get();
        if ( $userP ){
            return response()->json(['success' => true , 'message' =>"" , 'data'=>$userP ],200);
        } else{
            return response()->json(['success' => false, 'message' =>"user id error" , 'data'=> null ],400);
        }
    }
Http Verb URI Action
GET /water/{user_id} waterUser

對應的URI如上,但也有些建議可以把URI寫成 「 /{user_id}/userWater/ 」的更易理解的形式。

Update

預設作法
更新時,要知道每次請求要更新哪些欄位。

以底下的code為例,更新欄位的內容可能是$dietColumn裏6個參數之一,或是6種參數的排列組合。因此用 $request->filled($value)) 判斷有無傳入數值,再更新欄位寫入資料庫。

    public static $dietColumn = ['fruits', 'vegetables', 'grains', 'nuts', 'proteins', 'dairy'];
    
    /**
     * Update the specified resource in storage.
     *
     * @param \Illuminate\Http\Request $request
     * @param \App\userDiet $userDiet
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, userDiet $userDiet)
    {
        foreach (self::$dietColumn as $value) {
            if ($request->filled($value)) {
                $userDiet->$value = $request->$value;
            }
            $userDiet->save();
        }
        if ($userDiet == true) {
            return response()->json(['success' => true, 'message' => "update success", 'data' => null], 200);
        } else {
            return response()->json(['success' => false, 'message' => "update  error", 'data' => null], 400);
        }
    }

postman調整
如果body使用form-data,會無法使用put。
解法可以參考這篇,body 加欄位、方法改為post,router還是寫put不用額外調整。

delete

預設作法
直接輸入 $userWater 對應的id,即可刪除該筆資料

Http Verb URI Action
DELETE /userWater/{userWater_id} destroy
/**
     * Remove the specified resource from storage.
     *
     * @param \App\userWater $userWater
     * @return \Illuminate\Http\Response
     */
    public function destroy(userWater $userWater)
    {
        $userWater->delete();
        return response()->json(['success' => true , 'message' =>"delete success" , 'data'=>null ],200);
    }

resource not found

這系列的RESTful API作法,都建立於Laravel有個 Resource Controllers 的概念,讓我們可以透過以下action方式,只要知道resource model 的id (userWater的id),就可read/update/delete resource。

public function show(userWater $userWater)
public function update(Request $request, userWater $userWater)
public function destroy(userWater $userWater)

但給錯$userWater id 時,要怎麼提醒錯誤資訊呢?

可在「 app/Exceptions/Handler.php」的 render() ,設定 ModelNotFoundException的處理方式,讓Laravel幫忙抓到 resource model 的 id異常(不存在、軟刪除、錯誤id格式)等例外狀態。

 /**
 * Render an exception into an HTTP response.
 *
 */
 public function render($request, Throwable $exception)
 {
     if ($exception instanceof ModelNotFoundException) {
         return response()->json(['success' => false, 'message' =>"input id error" , 'data'=> null ],400);
      }
      return parent::render($request, $exception);
  }

參考資料
https://restfulapi.net/rest-architectural-constraints/
https://ihower.tw/blog/archives/1542
https://stackoverflow.com/questions/51302049/could-not-submit-form-data-through-postman-put-request
https://laravel.com/docs/8.x/controllers#resource-controllers
https://learnku.com/docs/laravel/7.x/controllers/7461#resource-controllers


上一篇
RESTful API (2) :Response
下一篇
Postman:API客戶端測試與線上文件
系列文
30天開發與部署 Laravel 專案30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言