Maison >développement back-end >Golang >Comment renvoyer une entité imbriquée après la création d'un nouvel objet ?
En PHP, comment renvoyer des entités imbriquées après la création d'un nouvel objet est une question courante. Lorsque nous devons créer un nouvel objet dans une classe et l'utiliser comme attribut d'une autre entité, nous devons prêter attention à certaines techniques et méthodes. Tout d’abord, nous pouvons créer un nouvel objet dans le constructeur de la classe et l’attribuer à la propriété. Nous pouvons ensuite utiliser le mot-clé $this pour référencer l'objet actuel et accéder à ses propriétés. De plus, nous pouvons également utiliser des méthodes statiques ou des modèles d'usine pour créer de nouveaux objets et les renvoyer à l'appelant. Quelle que soit la méthode utilisée, la clé pour renvoyer des entités imbriquées est de gérer correctement les relations entre les objets et de garantir qu'ils interagissent et transmettent correctement les données entre les entités. Grâce à ces méthodes, nous pouvons facilement créer et renvoyer des objets d'entité imbriqués en PHP.
Modèle account
包含嵌套结构 - currency
和 user
Lorsque je crée une nouvelle instance de account
dans la base de données et que je la renvoie ensuite dans la réponse, l'entité imbriquée est vide :
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}) }
Pour éviter ce problème, j'utilise une requête distincte pour actualiser les variables du compte :
db.DB.Create(&account) db.DB.Preload("User").Preload("Currency").Find(&account, account.ID) ctx.JSON(http.StatusCreated, gin.H{"data": account})
Est-ce le moyen le plus efficace et le plus correct d'obtenir les résultats souhaités ?
Je vais partager avec vous comment je gère habituellement cette situation. Tout d’abord, permettez-moi de partager le code.
main.go
Fichierspackage 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() }
Ici, je viens d'ajouter le code pour amorcer l'objet de base de données et d'y ajouter des données factices.
handlers/handlers.go
Fichierspackage 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) }
Dans ce fichier, je communique en fait avec la base de données en le faisant dans context
中传递的 db
. Maintenant, revenons à votre question.
Si la relation entre devise
//compte et utilisateur
/currency
//account 和 user
/account
之间的关系是 1:1
类型,那么,您应该依赖 preload
子句。这将在单独的查询中加载相关实体,而不是将其添加到 inner join
est de type 1:1
, alors vous devez vous fier à la clause preload
. Cela chargera les entités associées dans une requête distincte plutôt que de les ajouter à la clause inner join
.
S'il vous plaît dites-moi si cela résout votre problème, merci !
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!