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