Maison > développement back-end > Golang > le corps du texte

Comment renvoyer une entité imbriquée après la création d'un nouvel objet ?

PHPz
Libérer: 2024-02-10 21:40:15
avant
540 Les gens l'ont consulté

Comment renvoyer une entité imbriquée après la création dun 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.

Contenu des questions

Modèle account 包含嵌套结构 - currencyuser

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})
}


Copier après la connexion

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})
Copier après la connexion

Est-ce le moyen le plus efficace et le plus correct d'obtenir les résultats souhaités ?

Solution

Je vais partager avec vous comment je gère habituellement cette situation. Tout d’abord, permettez-moi de partager le code.

main.go Fichiers

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()
}
Copier après la connexion

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 Fichiers

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)
}
Copier après la connexion

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!

source:stackoverflow.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!