Is there a way to do BeforeCreate and BeforeUpdate hooks for each structure within a structure?

PHPz
Release: 2024-02-05 21:48:08
forward
859 people have browsed it

有没有办法为结构内的每个结构执行 BeforeCreate 和 BeforeUpdate 挂钩?

Question content

I have the following code:

type innerstructa struct {
 a string
}

type innerstructb struct {
 b string
}

func (a *a) beforecreate(scope *gorm.scope) error {
    return scope.setcolumn("a", uuid.new().string())
}

func (b *b) beforecreate(scope *gorm.scope) error {
    return scope.setcolumn("b", uuid.new().string())
}

type outerstruct struct {
    innerstructa
    innerstructb
    id      string `gorm:"type:varchar(40);not null"`
}
Copy after login

When I create the record:

outerStructObject := OuterStruct{
        ID:          "sample_ID",
    }
err := db.Create(&outerStructObject).Error
Copy after login

Only call one of the beforecreate() hooks. Other beforecreate are skipped.

gorm version is jinzhu/gorm v1.9.16

Is there a way to call both hooks when calling the create statement?

Expected beforecreate hooks to be called for two inner structures - innerstructa and innerstructb.


Correct answer


peter's comment is accurate, I will share my tests and comments here but using the official repositorygo -gorm/ gorm and the latest version v1.25.0 have very similar results and some changes in the api.

When creating an external registry, the internal object can be set like this:

func (o *outerstruct) beforecreate(tx *gorm.db) error {
    fmt.println("hook triggered: beforecreate for outerstruct")
    o.innerstructa.a = uuid.new().string()
    o.innerstructb.b = uuid.new().string()
    return nil
}
Copy after login

To trigger internal object hooks, you can only create them directly:

innera := innerstructa{
    a: "123",
}

errcreateinner := db.create(&innera).error
Copy after login

This is a complete isolated example:

package main

import (
    "fmt"
    "log"

    "github.com/google/uuid"
    "gorm.io/driver/sqlite"
    "gorm.io/gorm"
)

func main() {

    db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
    if err != nil {
        panic(err)
    }

    db.AutoMigrate(&InnerStructA{}, &InnerStructB{}, &OuterStruct{})

    outerStructObject := OuterStruct{
        ID: "sample_ID",
    }

    errCreate := db.Create(&outerStructObject).Error
    if err != nil {
        log.Fatal(errCreate)
    }

    var outer OuterStruct
    db.Last(&outer)
    fmt.Println("Last register: ", outer)

    // innerA := InnerStructA{
    //  A: "123",
    // }

    // errCreateInner := db.Create(&innerA).Error
    // if err != nil {
    //  log.Fatal(errCreateInner)
    // }
}

type InnerStructA struct {
    A string
}

type InnerStructB struct {
    B string
}

// This is not being called
func (a *InnerStructA) BeforeCreate(tx *gorm.DB) error {
    fmt.Println("Hook triggered: BeforeCreate for InnerStructA")
    // ...
    return nil
}

// This is not being called
func (b *InnerStructB) BeforeCreate(tx *gorm.DB) error {
    fmt.Println("Hook triggered: BeforeCreate for InnerStructB")
    // ...
    return nil
}

// This works!
func (o *OuterStruct) BeforeCreate(tx *gorm.DB) error {
    fmt.Println("Hook triggered: BeforeCreate for OuterStruct")
    o.InnerStructA.A = uuid.New().String()
    o.InnerStructB.B = uuid.New().String()
    return nil
}

type OuterStruct struct {
    InnerStructA
    InnerStructB
    ID string `gorm:"type:varchar(40);not null"`
}
Copy after login

The above is the detailed content of Is there a way to do BeforeCreate and BeforeUpdate hooks for each structure within a structure?. For more information, please follow other related articles on the PHP Chinese website!

source:stackoverflow.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template