There are plans to introduce go:generate scripts to automate the generation of record proxies in the near future.

The available core.Record and its helpers are usually the recommended way to interact with your data, but in case you want a typed access to your record fields you can create a helper struct that embeds core.BaseRecordProxy (which implements the core.RecordProxy interface) and define your collection fields as getters and setters.

By implementing the core.RecordProxy interface you can use your custom struct as part of a RecordQuery result like a regular record model. In addition, every DB change through the proxy struct will trigger the corresponding record validations and hooks. This ensures that other parts of your app, including 3rd party plugins, that don't know or use your custom struct will still work as expected.

Below is a sample Article record proxy implementation:

// article.go package main import ( "github.com/pocketbase/pocketbase/core" "github.com/pocketbase/pocketbase/tools/types" ) // ensures that the Article struct satisfy the core.RecordProxy interface var _ core.RecordProxy = (*Article)(nil) type Article struct { core.BaseRecordProxy } func (a *Article) Title() string { return a.GetString("title") } func (a *Article) SetTitle(title string) { a.Set("title", title) } func (a *Article) Slug() string { return a.GetString("slug") } func (a *Article) SetSlug(slug string) { a.Set("slug", slug) } func (a *Article) Created() types.DateTime { return a.GetDateTime("created") } func (a *Article) Updated() types.DateTime { return a.GetDateTime("updated") }

Accessing and modifying the proxy records is the same as for the regular records. Continuing with the above Article example:

func FindArticleBySlug(app core.App, slug string) (*Article, error) { article := &Article{} err := app.RecordQuery("articles"). AndWhere(dbx.NewExp("LOWER(slug)={:slug}", dbx.Params{ "slug": strings.ToLower(slug), // case insensitive match })). Limit(1). One(article) if err != nil { return nil, err } return article, nil } ... article, err := FindArticleBySlug(app, "example") if err != nil { return err } // change the title article.SetTitle("Lorem ipsum...") // persist the change while also triggerring the original record validations and hooks err = app.Save(article) if err != nil { return err }

If you have an existing *core.Record value you can also load it into your proxy using the SetProxyRecord method:

// fetch regular record record, err := app.FindRecordById("articles", "RECORD_ID") if err != nil { return err } // load into proxy article := &Article{} article.SetProxyRecord(record)