更新於 2024/10/23閱讀時間約 17 分鐘

第三方金流串接 – 產品功能Controller製作

    ※ 建立一個管理者的資料夾,負責建立不同的管理 — manager:

    raw-image

    ※ 在manager資料夾中,建立modelManager.ts:

    ※ 設定資料庫模型的管理:

    1. 匯入模組
    import { IProductModel, ProductModel } from "@/model/product";
    import { Knex } from "knex";

    程式碼解說:

    • 從 @/model/product 匯入 IProductModel 和 ProductModel。
    • 從 knex 匯入 Knex 資料庫模組。
    1. 定義 ModelContext 介面
    export interface ModelContext {
    productModel: IProductModel;
    }

    程式碼解說:

    定義一個介面 ModelContext,包含 productModel 屬性,類型為 IProductModel。

    1. 定義 modelManager 函數
    export const modelManager = ({ knexSql }: { knexSql: Knex }): ModelContext => {
    const productModel = ProductModel.createModel({ knexSql });
    return { productModel };
    }

    程式碼解說:

    • 定義 modelManager 函數,用來管理和初始化模型。
    • 函數接受一個參數 knexSql,類型為 Knex。
    • 使用 ProductModel.createModel 方法創建 productModel 實例。
    • 返回一個包含 productModel 的物件,符合 ModelContext 介面。

    ※ 調用 modelManager 函數:


    在app.ts新增程式碼:

    import { ModelContext, modelManager } from './manager/modelManager';//新增
    class App {
    private modelCtx: ModelContext;//新增

    constructor() {

    this.modelCtx = modelManager({ knexSql: this.knexSql });//新增

    }
    1. 匯入模組
    import { ModelContext, modelManager } from './manager/modelManager'; 

    程式碼解說:

    目的是從指定的路徑(./manager/modelManager)匯入兩個模組:ModelContext 和 modelManager。

    • ModelContext:這是一個介面,用來描述資料模型上下文的結構和類型。
    • modelManager:這是一個函數,用來初始化和管理資料模型,並返回一個包含所有資料模型實例的物件。

    2. 類別定義:

    class App {
    private modelCtx: ModelContext;

    程式碼解說:

    目的是在 App 類別中定義一個私有屬性 modelCtx,它的類型為 ModelContext。主要用途:

    • 強制型別:透過將 modelCtx 的類型設定為 ModelContext,可以確保 modelCtx 符合特定的結構和類型要求,這有助於在編譯時期捕捉潛在的錯誤。
    • 資料模型管理:modelCtx 用來存儲資料模型的上下文,這樣可以方便地在應用程式的其他地方訪問和操作這些資料模型。
    • 封裝性:private 關鍵字表示 modelCtx 屬性只能在 App 類別內部訪問,這增加了程式碼的封裝性和安全性,防止外部未經授權的訪問和修改。
    • "Ctx" 是 "Context" 的縮寫。通常用來表示一個上下文或環境,用來存儲和共享關鍵資料和設定。

    3.建構函數

    constructor() {
    this.modelCtx = modelManager({ knexSql: this.knexSql });
    }

    程式碼解說:

    目的是在 App 類別的建構函數中初始化資料模型上下文。

    • 呼叫 modelManager 函數,並將 knexSql 資料庫連接實例傳遞給它。
    • modelManager 函數會根據傳入的 knexSql 初始化資料模型,並返回包含這些模型的上下文物件。
    • 這個上下文物件被儲存在 this.modelCtx 屬性中。

    ※ 建立一個管理控制的資料夾,負責建立不同的控制 — controller:

    ※ 在controller資料夾中,建立productController.ts:

    ※ ProductController:專門處理產品相關 API 請求的控制器,包含產品資料的 CRUD(建立、讀取、更新、刪除)邏輯:

    1.匯入模組

    import { IProductModel } from "@/model/product";
    import { NextFunction, Request, Response } from "express";

    程式碼解說:

    • IProductModel:從 @/model/product 模組中匯入,定義產品模型的結構和方法。
    • NextFunction, Request, Response:從 express 模組中匯入,用於處理 HTTP 請求和回應。

    2.定義介面 IProductController

    export interface IProductController {
    //使用express.js的router API
    findAll(req: Request<any, any, any, any>,
    res: Response,
    _next: NextFunction): void;
    }

    程式碼解說:

    • 使用 export 導出這個介面,使其可以在其他模組中使用。
    • 定義了 findAll 方法 ,這個方法接受Express的三個參數,用於處理 API 請求:
      • req:類型為 Request<any, any, any, any>,表示 HTTP 請求對象。
      • res:類型為 Response,表示 HTTP 回應對象。
      • _next:類型為 NextFunction,表示中介軟體中的下一個函數。
    • 方法的返回類型為 void,表示這個方法不會有返回值。

    3.定義 ProductController 類別

    export class ProductController {
    private productModel: IProductModel;

    constructor({ productModel }: { productModel: IProductModel }) {
    this.productModel = productModel;
    }

    //傳到前端
    findAll: IProductController["findAll"] = async (_req, res, _next) => {
    const result = await this.productModel.findAll();
    res.json(result);
    }
    }

    程式碼解說:

    • 這個控制器類別的目的是使用 productModel 進行資料庫操作,並通過 Express.js 的 API 將資料返回給前端。
    • findAll 方法專門負責處理查詢所有產品資料的請求,並返回結果。
    • 定義並導出 ProductController 類別。
    • 宣告一個私有屬性 productModel,類型為 IProductModel。
    //類別定義:
    export class ProductController {
    private productModel: IProductModel;
    • constructor 建構函數接受一個物件參數包含 productModel 屬性,並將 productModel 賦值給類別的私有屬性。
    constructor({ productModel }: { productModel: IProductModel }) {
    this.productModel = productModel;
    }
    • 定義並實現 findAll 方法,用於處理從客戶端發送的請求。
    • 非同步地從 productModel 中查詢所有產品資料。
    • 將查詢結果以 JSON 格式返回給前端。
    findAll: IProductController["findAll"] = async (_req, res, _next) => {
    const result = await this.productModel.findAll();
    res.json(result);
    }

    ※ 補充說明:

    _req:

    這樣的命名通常表示這個參數在方法中沒有被使用。這是開發者的一種慣例,用 _ 作為前綴來表明這個參數在函數或方法中是未使用的,但依然需要保留它作為函數簽名的一部分。



    建立 ProductControllerProp介面,確保傳遞的資料正確無誤:

    1.定義 ProductControllerProp 介面

    interface ProductControllerProp {
    productModel: IProductModel;
    }

    程式碼解說:

    • 定義一個介面 ProductControllerProp,包含一個屬性 productModel,類型為 IProductModel。
    • "Prop" 是 "Property" 的縮寫,表示物件的屬性或屬性定義。在 ProductControllerProp 中,它代表了傳遞給 ProductController 的屬性集合。

    2.靜態方法 createConstructor:

    public static createConstructor({ productModel }: ProductControllerProp) {
    return new ProductController({ productModel });
    }

    程式碼解說:

    • 這是一個靜態方法,名為 createConstructor。
    • 方法接受一個 ProductControllerProp 類型的物件作為參數。
    • 返回一個新的 ProductController 實例,並將 productModel 傳遞給建構函數進行初始化。

    ※ 在Manager資料夾中,建立controllerManager.ts:


    ※ controllerManager:用來管理和初始化所有控制器的工具或函數:

    1.匯入模組

    import { ProductController, IProductController } from "@/controller/productController";
    import { ModelContext } from "./modelManager"


    程式碼解說:

    • ProductController:產品控制器,包含處理產品相關 API 請求的邏輯。
    • IProductController:產品控制器的介面,定義了控制器應該實現的方法結構。
    • ModelContext:資料模型的上下文,用來管理和訪問不同的資料模型。

    2.定義 ControllerContext 介面

    export interface ControllerContext {
    productController: IProductController;
    }

    程式碼解說:

    • 定義一個介面 ControllerContext,包含 productController 屬性,且該屬性的類型為 IProductController
    • 用於描述控制器上下文的結構。

    3.定義 controllerManager 函數

    export const controllerManger = ({
    modelCtx
    }: {
    modelCtx: ModelContext;
    }): ControllerContext => {
    const productController = ProductController.createConstructor({ productModel: modelCtx.productModel });

    return {
    productController
    }


    程式碼解說:

    • 目的是統一管理和初始化控制器。
    • 初始化參數接受一個包含 modelCtx 的物件參數,modelCtx 類型為 ModelContext,其中包含資料模型的上下文。
    • 創建 ProductController 實例:使用靜態方法 createConstructor 來創建 ProductController 的實例,並將 modelCtx 中的 productModel 傳遞給它。
    • 返回控制器上下文返回一個包含 productController 的物件,這個物件的類型符合 ControllerContext 介面。


    ※ 將 ProductController 和 controllerManager 加入 app.ts 為的是將這些控制器註冊到應用程式中,確保它們能夠處理來自客戶端的請求:

    import { ControllerContext } from './manager/controllerManager';//新增

    class App {
    controllerCtx: ControllerContext;//新增

    constructor() {

    this.controllerCtx = controllerManger({ modelCtx: this.modelCtx })//新增

    }

    程式碼解說:

    1.匯入模組

    import { ControllerContext } from './manager/controllerManager';
    • 定義控制器上下文的結構。確保你可以在程式中一致地使用控制器,並享受型別檢查帶來的安全性。

    2.定義 App 類別

    class App {
    controllerCtx: ControllerContext;
    • 型別安全:指定 controllerCtx 的類型為 ControllerContext,確保它符合預期的結構和型別,增加程式碼的安全性。
    • 組織和管理控制器:controllerCtx 用於存儲所有初始化的控制器,例如 ProductController。這樣可以統一管理應用程式中的控制器,讓程式碼更具結構性和組織性。
    • 方便訪問:將 controllerCtx 屬性存儲在 App 類別中,方便在應用程式的其他地方訪問和使用這些控制器。

    3.建構函數

    constructor() {
    this.controllerCtx = controllerManger({ modelCtx: this.modelCtx });
    }
    • 初始化控制器上下文:透過調用 controllerManager 函數,並傳入 modelCtx,來初始化控制器上下文。
    • 儲存控制器實例:controllerManager 返回的控制器上下文被賦值給 this.controllerCtx,這樣應用程式中的其他部分可以方便地訪問和使用這些控制器。
    分享至
    成為作者繼續創作的動力吧!
    © 2024 vocus All rights reserved.