在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
子句中。
请告诉我这是否解决了您的问题,谢谢!
以上就是创建新对象后如何返回嵌套实体?的详细内容,更多请关注编程网其它相关文章!