Model is a more advanced struct.With Relationships,Events,Connection,TimeStamps features.
Conventions
First,let’s see how to define a model.
A model should be a struct with an embed anonymous struct pointer of type goeloquent.EloquentModel
primaryKey should be int64 with tag goelo:"primaryKey"
Each database table column should have a tag goelo:"column:databasefiledname"
By default , we will use the model’s SnakeCase name as table name (e.g. ‘User’ as ‘user’,’UserInfo’ as ‘user_info’’) ,you can change this by implement type TableName interface
By default , we will use the connection with name default.You can change this by implement type ConnectionName interface.
When creating model,we will set timestamps for you if you have a tag goelo:"column:created_at;CREATED_AT"
When updating model,we will set timestamps for you if you have a tag goelo:"column:updated_at;UPDATED_AT"
Example of User model
type UserT struct { *goeloquent.EloquentModel Id int64 `goelo:"column:id;primaryKey"` UserName string `goelo:"column:name"` Age int `goelo:"column:age"` ViewedPosts []Post `goelo:"BelongsToMany:ViewedPostsRelation"` Friends []UserT `goelo:"BelongsToMany:FriendsRelation"` Address Address `goelo:"HasOne:AddressRelation"` Posts []Post `goelo:"HasMany:PostsRelation"`
var u UserT DB.Model(&u).Where(“age”, “>”, 200).Update(map[string]interface{}{ “age”: goeloquent.Expression{Value: “age + 10”}, “phone”: “unknown”, }) //{update users set age = age + 10 , phone = ? where age > ? [unknown 200] {0xc000140090 0xc00001eea0} 72.325303ms}
You can use `Only/Except` to specify which columns to be inserted/updated
```golang type Temp struct { Id int64 `goelo:"column:tid;primaryKey"` Name string `goelo:"column:name"` Status int8 `goelo:"column:status"` } type TempB struct { Id int64 Name string }
var tagt, tag Temp var tagtt TempB tag.Name = "test" tagt.Name = "test" tagt.Status = 1 tagtt.Name = "test" DB.Table("tag").Insert(tag) //"insert into `tag` (`name`) values (?)"
DB.Table("tag").Only("name").Insert(tagt) //"insert into `tag` (`name`) values (?)"
DB.Model().Except("id").Insert(&tagtt) //"insert into `tag` (`name`) values (?)"
Scopes
FuncScope
funcAgeScope(builder *goeloquent.Builder) *goeloquent.Builder { return builder.Where("age", ">", 18) } b1 := DB.Query() b1.Select().From("users").Scopes(AgeScope, ScopeFunc).Get(&us) //{select * from `users` where `age` > ? order by `id` desc [18] <nil> 40.616291ms}
Model Global Scope
Add global scope to model
type Tag1 struct { *goeloquent.EloquentModel ID int64`goelo:"column:tid;primaryKey"` Name string`goelo:"column:name"` }
var tags []Tag1 b := DB.Model(&Tag1{}) _, err := b.Pretend().Get(&tags) //"select * from `tag1` where `active` = ?"
Remove global scope
var tags []Tag1 b := DB.Model(&Tag1{}) _, err := b.Pretend().WithOutGlobalScopes("active").Get(&tags) //"select * from `tag1`"
Events
Like Laravel,we have model events in model’s lifecycle. We have saving,saved,creating,created,updating,updated,deleting,deleted model events. Below is the event order.
For create saving->creating->insert operation->created->saved For update saving->updating->update operation ->updated->saved For delete deleting->delte operation->deleted In any ing event return an error will abort the database operation
func (u *UserT) Creating(builder *goeloquent.Builder) (err error) { if u.Age <= 0 { u.Age = 10 //change it } fmt.Println(u.Exists)//false u.GetOrigin()//map with default values u.GetDirty() //map with non-zero values u.GetChanges() //it's not saved to dasebase so empty if strings.Contains(u.NickName.String, "shit") { return errors.New("bad name") //return error to abort create } return nil //if it return error, abort sql execution with err "abort by func" } func (u *UserT) Created(builder *goeloquent.Builder)(err error) { u.GetOrigin() //same with creating u.GetDirty() //same with creating and an `id` value u.GetChanges() //same with creating return nil } func (u *UserT) Updating(builder *goeloquent.Builder) (err error) { u.GetOrigin()//original databse value u.GetDirty()//map with changed values u.GetChanges() // empty map return nil } func (u *UserT) Updated(builder *goeloquent.Builder)(err error) { u.GetOrigin()//same with updating u.GetDirty()//same with updating u.GetChanges()//same with GetDirty return nil
} func (u *UserT) Saving(builder *goeloquent.Builder) (err error) { u.GetOrigin()//when create same with creating,when update same with updating u.GetDirty()//when create same with creating,when update same with updating u.GetChanges()//when create same with creating,when update same with updating return nil } func (u *UserT) Saved(builder *goeloquent.Builder)(err error) { u.GetOrigin() //when create same with created u.GetDirty()//when create same with created u.GetChanges()//when create same with created return nil
You can call GetOrigin to get the original attributes since you retrive it from database. If it’s just created and haven’t been save to database it will be a map[string]interface with all default values. You can get a map[string]interface with all changed value than hasn’t been save to databse yet by call GetDirty.
Mute Events
If you don’t want trigger event use Mute()
var u UserT DB.Model(&UserT{}).Find(&u, 22) u.Age = 23 u.Mute(goeloquent.EventUpdating,goeloquent.EventUpdated,goeloquent.EventSaving,goeloquent.EventSaved).Save()
If you are creating a model and wants to mute some event call DB.Boot(&u) before you use Mute