iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 8
1
Modern Web

RRR撞到不負責之 Laravel + Nuxt.js 踩坑全紀錄系列 第 8

Day 08. 瘦,是一種生活 - 減脂後的 Controller

  • 分享至 

  • xImage
  •  

在連續兩天的減重之後,今天來看看 controller 瘦身後的結果吧 (聽起來好像賣膏藥的 XD)! 進入正題之前特別說明一下, controller 中的每一個 function 都是一個完整運作一套商業邏輯的地方,簡單來說一個 API 就是對應一個 controller 中的 function。

最基本的 controller 可以在 cmd 中執行下面指令產出:

php artisan make:controller <controller 名稱>

預設的 controller 很單純、只繼承 App\Http\Controller 而已

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class PostController extends Controller
{
    //
}

接著我們接續前兩天更新 post 的範例,補完一個 api 基本會有的所有邏輯吧!

  1. 首先,先建立一個 function
    public function editPost()
    {

    }
  1. 接著我們規劃一下,幾乎所有的功能都有下列步驟

    1. 接收 client 傳遞進來的資料 (request)
    2. 檢查、過濾 request 的合法性
    3. 資料前處理
    4. 執行各種功能和取得需要的資料
    5. 整合功能的回傳資料成為回傳給 client 的資料 (response)
  2. 我們逐步撰寫完成後的結果如下。

    1. 如果 service 會在同個 controller 的其他 function 用到,可以改在 __construct 中注入。至於 request 的部分會在明後天 FormRequest 有更詳細的說明。
    2. 所有進入 server 的資料都應該先檢查過,減少被攻擊或錯誤的產生,這部分就目前來說變成是 controller 中最肥的地方,同樣的在明後天 validation 有更詳細的說明。
    3. 資料前處理的部分,我們只取與 post 有關的資料出來更新,這部分在個人的經驗中,比較複雜的資料通常也會占 controller 很大一部份,但這是必須的。
    4. 根據需求執行 service 方法,顯而易見的是,因為我們把商業邏輯的部分拆入 service 和 repository 之中,因此在少了 10 - 20 行的情況下,閱讀輕鬆很多,也可以快速理解這支 API 主要功能,若有必要再進入 service 或 repository 檢查即可,同時程式更單一化且有彈性。
    5. 根據執行 service 的結果回傳相對應的 response 給 client。
    use Illuminate\Http\Request;
    
             // 01. DI 傳入 request 和 service 等資料
    function edit(PostService $postService, Request $request)
    {
        // 02. 檢查、過濾 request
        // 例如,必須要有呼叫 api 的使用者 ID、要修改的 post ID 以及其他必要的資料
        $validUserId = $request->has('userId') && is_int($request['userId']);
        $validPostId = $request->has('postId') && is_int($request['postId']);
        $hasTitle = $request->has('title');
        $hasContent = $request->has('content');
        // 其中一個不合法就回傳 http status 設為 422 的 response
        if (!$validUserId || !$validPostId || !$hasTitle || !$hasContent) {
            return response()->json([
                'success' => false,
                'message' => 'bad request data'
            ], 422);
        }

        // 03. 資料前處理
        $updateData = $request->only(['title', 'content']);

        // 04. 執行 service
        try {
            // 更新 post 資料並取回新的 post 結果
            $updatedPost = $postService->updatePost($request['userId'], $request['postId'], $updateData);
            // 將 post model 轉換為 api resource 形式
            $updatedPost = $postService->modelToAPIResource(updatedPost);
            // 05. 回傳成功結果
            return response()->json([
                'success' => true,
                'message' => null,
                'data' => $updatedPost
            ]);
        } catch (\Exception $exception) {
            // 05. 回傳執行過程中出現錯誤的資訊
            $exMessage = $exception.getMessage();
            $exCode = $exception.getCode();
            return response()->json([
                'success' => false,
                'message' => "catch exception:{$exMessage}",
                'code' => $exCode,
            ], 500);
        }
    }

在有了 service 和 repository 之後,controller 輕量很多、易寫也好讀,不過我們在上面的範例看到 request 驗證的部分就占很重,但又不能省略...,好在 Laravel 有提供開發者方便驗證的作法,我們就於明後兩天分別介紹 FormRequestvalidation 把 controller 的工作再分散出去,讓日後更好維護吧!


上一篇
Day 07. Controller 減重計畫 (Service 篇)
下一篇
Day 09. Request 驗證可以再簡單一點 (Validation)
系列文
RRR撞到不負責之 Laravel + Nuxt.js 踩坑全紀錄31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言