首頁 > 後端開發 > Golang > 建立新物件後如何返回嵌套實體?

建立新物件後如何返回嵌套實體?

PHPz
發布: 2024-02-10 21:40:15
轉載
583 人瀏覽過

建立新物件後如何返回嵌套實體?

在PHP中,建立新物件後如何返回嵌套實體是一個常見的問題。當我們需要在一個類別中建立一個新的對象,並將其作為另一個實體的屬性時,我們需要注意一些技巧和方法。首先,我們可以在類別的建構子中建立新的對象,並將其賦值給屬性。然後,我們可以使用$this關鍵字來引用當前對象,並存取其屬性。另外,我們也可以使用靜態方法或工廠模式來建立新的對象,並將其傳回給呼叫者。無論哪種方法,傳回巢狀實體的關鍵是正確地處理物件之間的關聯關係,確保它們在各個實體之間正確地互動和傳遞資料。透過這些方法,我們可以輕鬆地在PHP中建立和傳回嵌套的實體物件。

問題內容

模型 account 包含巢狀結構 - currencyuser

當我在資料庫中建立 account 的新實例,然後在回應中傳回它時,巢狀實體為空:

type account struct {
    basemodel
    name       string          `gorm:"size:64;not null" json:"name"`
    balance    decimal.decimal `gorm:"type:decimal(16, 2);default:0;not null;" json:"balance"`
    userid     int             `gorm:"not null" json:"-"`
    user       user            `gorm:"foreignkey:userid" json:"user"`
    currencyid int             `gorm:"not null" json:"-"`
    currency   currency        `gorm:"foreignkey:currencyid" json:"currency"`
}

type createaccountbody struct {
    name       string          `json:"name" binding:"required"`
    balance    decimal.decimal `json:"balance"`
    currencyid int             `json:"currency_id" binding:"required"`
}

func createaccount(ctx *gin.context) {
    body := createaccountbody{}

    if err := ctx.bind(&body); err != nil {
        log.println("error while binding body:", err)
        ctx.json(
            http.statusbadrequest,
            gin.h{"error": "wrong request parameters"},
        )
        return
    }

    account := account {
        name:       body.name,
        balance:    body.balance,
        currencyid: body.currencyid,
        userid:     1,
    }
    
    if result := db.db.create(&account); result.error != nil {
        log.println("unable to create an account:", result.error)
    }    

    ctx.json(http.statuscreated, gin.h{"data": account})
}


登入後複製

為了避免此問題,我使用單獨的查詢來刷新帳戶變數:

db.DB.Create(&account)
db.DB.Preload("User").Preload("Currency").Find(&account, account.ID)
ctx.JSON(http.StatusCreated, gin.H{"data": account})
登入後複製

這是達到預期結果的最有效、最正確的方法嗎?

解決方法

我將與您分享我通常是如何處理這種情況的。首先,讓我分享一下程式碼。

main.go 檔案

package main

import (
    "context"

    "gogindemo/handlers"

    "github.com/gin-gonic/gin"
    "gorm.io/driver/postgres"
    "gorm.io/gorm"
)

var (
    db  *gorm.db
    ctx *gin.context
)

func init() {
    dsn := "host=localhost user=postgres password=postgres dbname=postgres port=5432 sslmode=disable"
    var err error
    db, err = gorm.open(postgres.open(dsn), &gorm.config{})
    if err != nil {
        panic(err)
    }

    db.automigrate(&handlers.currency{})
    db.automigrate(&handlers.user{})
    db.automigrate(&handlers.account{})
}

func adddb() gin.handlerfunc {
    return func(ctx *gin.context) {
        ctx.request = ctx.request.withcontext(context.withvalue(ctx.request.context(), "db", db))
        ctx.next()
    }
}

func main() {
    db.create(&handlers.user{id: 1, name: "john doe"})
    db.create(&handlers.user{id: 2, name: "mary hut"})
    db.create(&handlers.currency{id: 1, name: "eur"})
    db.create(&handlers.currency{id: 2, name: "usd"})

    r := gin.default()
    r.post("/account", adddb(), handlers.createaccount)

    r.run()
}
登入後複製

在這裡,我剛剛添加了用於引導資料庫物件的程式碼並向其中添加了一些虛擬資料。

handlers/handlers.go 檔案

package handlers

import (
    "net/http"

    "github.com/gin-gonic/gin"
    "github.com/shopspring/decimal"
    "gorm.io/gorm"
)

type User struct {
    Id   int
    Name string
}

type Currency struct {
    Id   int
    Name string
}

type Account struct {
    Id         int
    Name       string          `gorm:"size:64;not null" json:"name"`
    Balance    decimal.Decimal `gorm:"type:decimal(16, 2);default:0;not null;" json:"balance"`
    UserID     int             `gorm:"not null" json:"-"`
    User       User            `gorm:"foreignKey:UserID" json:"user"`
    CurrencyID int             `gorm:"not null" json:"-"`
    Currency   Currency        `gorm:"foreignKey:CurrencyID" json:"currency"`
}

type CreateAccountBody struct {
    Name       string          `json:"name" binding:"required"`
    Balance    decimal.Decimal `json:"balance"`
    CurrencyID int             `json:"currency_id" binding:"required"`
}

func CreateAccount(c *gin.Context) {
    db, ok := c.Request.Context().Value("DB").(*gorm.DB)
    if !ok {
        c.JSON(http.StatusInternalServerError, gin.H{"error": "internal server error"})
        return
    }
    var accountReq CreateAccountBody
    if err := c.BindJSON(&accountReq); err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": "wrong request body payload"})
        return
    }

    // create Account & update the "account" variable
    account := Account{Name: accountReq.Name, Balance: accountReq.Balance, CurrencyID: accountReq.CurrencyID, UserID: 1}
    db.Create(&account).Preload("Currency").Preload("User").Find(&account, account.Id)

    c.IndentedJSON(http.StatusCreated, account)
}
登入後複製

在此文件中,我實際上透過在 context 中傳遞的 db 與資料庫進行通訊。現在,回到你的問題。
如果currency//account 和user/account 之間的關係是1:1類型,那麼,您應該依賴preload 子句。這將在單獨的查詢中載入相關實體,而不是將其新增至 inner join 子句中。

請告訴我這是否解決了您的問題,謝謝!

以上是建立新物件後如何返回嵌套實體?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:stackoverflow.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板