> For the complete documentation index, see [llms.txt](https://zakimaliki.gitbook.io/gofiber/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://zakimaliki.gitbook.io/gofiber/basic-backend-dengan-gofiber-part-2/membuat-relasi-dengan-gorm-di-gofiber.md).

# Membuat relasi dengan gorm di Gofiber

Baik, mari kita lanjutkan dengan membuat model, migration, dan API CRUD untuk tabel `category` dengan relasi one-to-many dengan tabel `product`. Berikut adalah langkah-langkahnya:

#### 1. Buat Migration untuk Tabel Category

Pertama, kita perlu membuat migration untuk tabel `category` dengan menambahkan foreign key ke tabel `product`.

**helpers/migration.go**

```go
package helpers

import (
	"gofiber/src/configs"
	"gofiber/src/models"
)

func Migration() {
	configs.DB.AutoMigrate(&models.Product{}, &models.Category{})
}
```

**models/Category.go**

```go
package models

import (
	"gofiber/src/configs"

	"gorm.io/gorm"
)

type Category struct {
	gorm.Model
	Name     string       `json:"name"`
	Image    string       `json:"image"`
	Products []ApiProduct `json:"products"`
}

type ApiProduct struct {
	Name       string  `json:"name" `
	Price      float64 `json:"price" `
	Stock      int     `json:"stock" `
	CategoryID uint    `json:"category_id"`
}

func SelectAllCategories() []*Category {
	var categories []*Category
	configs.DB.Preload("Products", func(db *gorm.DB) *gorm.DB {
		var items []*ApiProduct
		return db.Model(&Product{}).Find(&items)
	}).Find(&categories)
	return categories
}

func SelectCategoryById(id int) *Category {
	var category Category
	configs.DB.Preload("Products",
		func(db *gorm.DB) *gorm.DB {
			var items []*ApiProduct
			return db.Model(&Product{}).Find(&items)
		}).First(&category, "id = ?", id)
	return &category
}

func PostCategory(category *Category) error {
	result := configs.DB.Create(&category)
	return result.Error
}

func UpdateCategory(id int, updatedCategory *Category) error {
	result := configs.DB.Model(&Category{}).Where("id = ?", id).Updates(updatedCategory)
	return result.Error
}

func DeleteCategory(id int) error {
	result := configs.DB.Delete(&Category{}, "id = ?", id)
	return result.Error
}
```

Dalam implementasi di atas, kita menggunakan `Preload("Products")` untuk memuat produk yang terkait dengan setiap kategori yang dipilih. Ini memastikan bahwa ketika Anda mengambil semua kategori atau kategori berdasarkan ID, produk-produk yang terkait juga dimuat ke dalam struktur data kategori.

**models/Product.go**

```go
package models

import (
	"gofiber/src/configs"

	"gorm.io/gorm"
)

type Product struct {
	gorm.Model
	Name       string   `json:"name"`
	Price      float64  `json:"price"`
	Stock      int      `json:"stock"`
	CategoryID uint     `json:"category_id"`
	Category   Category `gorm:"foreignKey:CategoryID"`
}

func SelectAllProducts() []*Product {
	var items []*Product
	configs.DB.Preload("Category").Find(&items)
	return items
}

func SelectProductById(id int) *Product {
	var item Product
	configs.DB.Preload("Category").First(&item, "id = ?", id)
	return &item
}

func PostProduct(item *Product) error {
	result := configs.DB.Create(&item)
	return result.Error
}

func UpdateProduct(id int, newProduct *Product) error {
	var item Product
	result := configs.DB.Model(&item).Where("id = ?", id).Updates(newProduct)
	return result.Error
}

func DeleteProduct(id int) error {
	var item Product
	result := configs.DB.Delete(&item, "id = ?", id)
	return result.Error
}
```

#### 2. Buat API CRUD untuk Category

Kemudian, mari buat API CRUD untuk mengelola data kategori.

**controllers/CategoryController.go**

```go
package controllers

import (
	"gofiber/src/models"
	"strconv"

	"github.com/gofiber/fiber/v2"
)

func GetAllCategories(c *fiber.Ctx) error {
	categories := models.SelectAllCategories()
	return c.JSON(categories)
}

func GetCategoryById(c *fiber.Ctx) error {
	id, _ := strconv.Atoi(c.Params("id"))
	category := models.SelectCategoryById(id)
	return c.JSON(category)
}

func CreateCategory(c *fiber.Ctx) error {
	var category models.Category
	if err := c.BodyParser(&category); err != nil {
		c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
			"message": "Invalid request body",
		})
		return err
	}
	models.PostCategory(&category)
	return c.Status(fiber.StatusCreated).JSON(fiber.Map{
		"message": "Category created successfully",
	})
}

func UpdateCategory(c *fiber.Ctx) error {
	id, _ := strconv.Atoi(c.Params("id"))

	var updatedCategory models.Category
	if err := c.BodyParser(&updatedCategory); err != nil {
		c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
			"message": "Invalid request body",
		})
		return err
	}
	models.UpdateCategory(id, &updatedCategory)

	return c.Status(fiber.StatusOK).JSON(fiber.Map{
		"message": "Category updated successfully",
	})
}

func DeleteCategory(c *fiber.Ctx) error {
	id, _ := strconv.Atoi(c.Params("id"))
	models.DeleteCategory(id)
	return c.Status(fiber.StatusOK).JSON(fiber.Map{
		"message": "Category deleted successfully",
	})
}
```

**routes/main.go**

Tambahkan rute baru untuk API CRUD kategori.

```go
package routes

import (
	"gofiber/src/controllers"

	"github.com/gofiber/fiber/v2"
)

func SetupRoutes(app *fiber.App) {
	// Product routes
	app.Get("/products", controllers.GetAllProducts)
	app.Get("/product/:id", controllers.GetProductById)
	app.Post("/product", controllers.CreateProduct)
	app.Put("/product/:id", controllers.UpdateProduct)
	app.Delete("/product/:id", controllers.DeleteProduct)

	// Category routes
	app.Get("/categories", controllers.GetAllCategories)
	app.Get("/category/:id", controllers.GetCategoryById)
	app.Post("/category", controllers.CreateCategory)
	app.Put("/category/:id", controllers.UpdateCategory)
	app.Delete("/category/:id", controllers.DeleteCategory)
}
```

Dengan langkah-langkah ini, Anda telah menambahkan model, migration, dan API CRUD untuk kategori dengan relasi one-to-many dengan produk. Anda juga telah mengintegrasikan API kategori dengan rute aplikasi Anda.

sumber : [Dokumentasi](https://gorm.io/docs/has_one.html)
