iT邦幫忙

2025 iThome 鐵人賽

DAY 24
0

接下來,我們要新增 Category 的 API,讓前端可直接讀取目前所有的分類、新增、修改、刪除分類。然後再調整讀取分類的那支 API,讓它一起回傳每個分類下的任務。
這樣,就完成 To-do List 的大致樣子了!
/images/emoticon/emoticon07.gif


1. 新增 Category API

我們要新增 Category CRUD 的功能,API 的內容跟前面一開始建立 task API 的步驟一樣,如果忘記了或不確定可以參考 Day 11 ~ Day 14 天的文章,它有比較詳細的介紹。這邊我就分享 apiHandler.go 的 Categories 函式內容,剩下的 taskService.gotaskRepo.go 再依照程式邏輯自行完成~

  • 取得所有 Categories 的類別:
// GET /categories
func GetCategories(c *gin.Context){
	categories := taskService.GetCategories()
	c.JSON(http.StatusOK, categories)
}
  • 新增 Categories 類別:
// POST /categories
func AddCatogories(c *gin.Context){
	var input model.Category
	err := c.ShouldBindJSON(&input)
	if(err != nil){
		c.Error(taskService.ErrInvalidInput)
		return
	}

	newCategories, err := taskService.AddCategories(&input)
	if err != nil {
		c.Error(err)
		return
	}
	c.JSON(http.StatusOK, newCategories)
}
  • 修改 Categories 類別:
// PATCH /categories/:id
func UpdateCategories(c *gin.Context) {
	get_id := c.Param("id")
	id, err := strconv.Atoi(get_id)

	if err != nil {
		c.Error(taskService.ErrInvalidID)
		return
	}

	var input model.UpdateCategory
	if err := c.ShouldBindJSON(&input); err != nil {
		c.Error(taskService.ErrInvalidInput)
		return
	}

	editCategory, err := taskService.UpdateCategories(id, input)
	if err != nil{
		c.Error(err)
		return
	}
	c.JSON(http.StatusOK, editCategory)
}
  • 刪除 Categories 類別:
// DELETE /categories/:id
func DeleteCategories(c *gin.Context){
	get_id := c.Param("id")
	id, err := strconv.Atoi(get_id)
	if err != nil {
		c.Error(taskService.ErrInvalidID)
		return
	}

	err = taskService.DeleteCategories(id)
	if err != nil{
		c.Error(err)
		return
	}
	c.JSON(http.StatusOK, gin.H{"message": "Delete successfully"})
}

完成 API 的函式之後,再來要更新 router,把剛剛新增的 API 路徑更新到 main.go 檔案:

r.GET("/categories", apiHandler.GetCategories)
r.POST("/categories", apiHandler.AddCatogories)
r.PATCH("/categories/:id", apiHandler.UpdateCategories)
r.DELETE("/categories/:id", apiHandler.DeleteCategories)

這樣就設定完成了!接下來可以來測試看看 API~


2. 測試與修改

完成上述 Category API 之後,輸入:go run main.go ,啟動 server 看看 API 回傳的內容。
這次我們使用 Postman 來測試 API!

Postman 是一套測試 API 非常好用的工具,模擬 HTTP 的各種請求方式,讓開發者可以快速的知道 API 的請求結果。

有興趣深入了解的大家可以參考以下資訊:
Postman 官網:https://www.postman.com/
Postman 教學:https://ithelp.ithome.com.tw/articles/10201503
以下是測試結果:

  • GET /categories

    回傳:

    [
        {
            "ID": 1,
            "CreatedAt": "2025-10-06T00:05:49.595659+08:00",
            "UpdatedAt": "2025-10-06T00:05:49.595659+08:00",
            "DeletedAt": null,
            "Name": "學習"
        },
        {
            "ID": 2,
            "CreatedAt": "2025-10-06T00:12:58.792427+08:00",
            "UpdatedAt": "2025-10-06T14:07:31.832216+08:00",
            "DeletedAt": null,
            "Name": "工作"
        }
    ]
    
  • POST /categories

    輸入:

    {
        "Name": "運動"
    }
    

    回傳:

    {
        "ID": 2,
        "CreatedAt": "2025-10-06T00:12:58.792427+08:00",
        "UpdatedAt": "2025-10-06T00:12:58.792427+08:00",
        "DeletedAt": null,
        "Name": "運動",
        "Tasks": null
    }
    
  • PATCH /categories/:id

    修改 id=2 的資料: /categories/2。
    輸入:

    {  	
    	"Name":"工作"
    }
    

    回傳:

    {
        "ID": 2,
        "CreatedAt": "2025-10-06T00:12:58.792427+08:00",
        "UpdatedAt": "2025-10-06T14:07:31.832216+08:00",
        "DeletedAt": null,
        "Name": "工作",
        "Tasks": null
    }
    
  • DELETE /categories/:id

    刪除 id=3 的資料: /categories/3。
    回傳:

    {
        "message": "Delete successfully"
    }
    

上面就是 API 測試的結果~ 但是每一個回傳資料都有 CreatedAtUpdatedAtDeletedAt 這三個欄位,這是記錄在資料庫裡面的時間戳,可是前端不一定會需要這些資訊,所以後端就必須隱藏這些資料再傳給前端!

另外,我希望在讀取所有分類的時候,也可以同時看到每個類別底下的所有任務,這樣回傳給前端的時候,資料會更清楚~

綜合以上的需求,我需要修改的就是 taskModel.go 檔案裡面的資料結構!

  • 隱藏 CreatedAtUpdatedAtDeletedAt 三個欄位:

    把原本的 Task 與 Category 兩個結構裡面的 gorm.Model 移除,因為 gorm.Model 本身內建欄
    位ID、CreatedAt、UpdatedAt、DeletedAt,所以這是原因!

    那要怎麼隱藏呢?
    → 可以直接刪掉,然後定義需要的欄位即可!

    type Task struct {
    	ID     uint   `json:"id" gorm:"primaryKey"`
    	Item   string `json:"item"`
    	Status bool   `json:"status"`
    	CategoryID uint 
    }
    
    type Category struct {
    	ID         uint   `json:"id" gorm:"primaryKey"`
    	Name      string    `gorm:"not null;unique"`
    }
    
  • 新增每個分類的所有任務:

    在 Category 資料結構裡新增 Tasks []Task 這一行,讓 Category 資料表連結 Task 資料:

    type Category struct {
    	ID        uint   `json:"id" gorm:"primaryKey"`
    	Name      string    `gorm:"not null;unique"`
    	Tasks     []Task    `gorm:"foreignKey:CategoryID"`   //與 Task 資料表連結
    }
    

    然後再到 taskRepo.go 檔案裡的 GetCategories() 函式中新增這一行程式:

    database.DB.Preload("Tasks").Find(&categories)
    
    • Preload("Tasks") 是 GORM 的關鍵字,它會自動幫你把任務所屬的分類一起查出來。非常的方便!要記得 Preload() 引號裡的名稱要與 Category 結構裡的名稱定義一樣,不然會抓不到資料喔~

完成修改之後,我們再重新 GET Category 的資料,就會看到每個分類底下的所有任務,而且時間戳也都隱藏了,這樣子資料就變得非常乾淨、整齊!
回傳:

[
    {
        "id": 1,
        "Name": "學習",
        "Tasks": [
            {
                "id": 5,
                "item": "寫作業",
                "status": false,
                "CategoryID": 1
            }
        ]
    },
    {
        "id": 2,
        "Name": "工作",
        "Tasks": []
    },
    {
        "id": 3,
        "Name": "運動",
        "Tasks": []
    }
]

上一篇
Day23 - ORM 關聯:新增任務分類
系列文
Go,一起成為全端吧!—— 給前端工程師的 Golang 後端學習筆記24
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言