文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

创建新对象后如何返回嵌套实体?

2024-02-10 21:03

关注

在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 子句中。

请告诉我这是否解决了您的问题,谢谢!

以上就是创建新对象后如何返回嵌套实体?的详细内容,更多请关注编程网其它相关文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯