新聞中心
雖然?gvalid?已經內置了常見的數(shù)十種校驗規(guī)則,但是在部分業(yè)務場景下我們需要自定義校驗規(guī)則,特別是一些可以重復使用的業(yè)務相關的校驗規(guī)則。當然,?gvalid?如此的強大和貼心,她已經為您考慮得如此周全。自定義校驗規(guī)則可以實現(xiàn)靈活性強,可復用性高的校驗特性。

創(chuàng)新互聯(lián)建站-專業(yè)網站定制、快速模板網站建設、高性價比黎平網站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式黎平網站制作公司更省心,省錢,快速模板網站建設找我們,業(yè)務覆蓋黎平地區(qū)。費用合理售后完善,10余年實體公司更值得信賴。
相關數(shù)據(jù)結構
自定義規(guī)則方法定義,以及對應的輸入?yún)?shù)數(shù)據(jù)結構。
// RuleFuncInput holds the input parameters that passed to custom rule function RuleFunc.
type RuleFuncInput struct {
// Rule specifies the validation rule string, like "required", "between:1,100", etc.
Rule string
// Message specifies the custom error message or configured i18n message for this rule.
Message string
// Value specifies the value for this rule to validate.
Value *gvar.Var
// Data specifies the `data` which is passed to the Validator. It might be a type of map/struct or a nil value.
// You can ignore the parameter `Data` if you do not really need it in your custom validation rule.
Data *gvar.Var
}
// RuleFunc is the custom function for data validation.
type RuleFunc func(ctx context.Context, in RuleFuncInput) error方法參數(shù)簡要說明:
- 上下文參數(shù)?
ctx?是必須的。 - ?
RuleFuncInput?數(shù)據(jù)結構說明: - ?
Rule?表示當前的校驗規(guī)則,包含規(guī)則的參數(shù),例如:?required?, ?between:1,100?, ?length:6?等等。 - ?
Message?參數(shù)表示在校驗失敗后返回的校驗錯誤提示信息。 - ?
Value?參數(shù)表示被校驗的數(shù)據(jù)值,注意類型是一個?*gvar.Var?泛型,因此您可以傳遞任意類型的參數(shù)。 - ?
Data?參數(shù)表示校驗時傳遞的參數(shù),例如校驗的是一個?map?或者?struct?時,往往在聯(lián)合校驗時有用。需要注意的是,這個值是運行時輸入的,值可能是?nil?。
自定義錯誤默認情況下已支持?i18n?特性,因此您只需要按照 ?gf.gvalid.rule.自定義規(guī)則名稱? 配置?i18n?轉譯信息即可,該信息在校驗失敗時會自動從?i18n?管理器獲取后,通過?Message?參數(shù)傳入給您注冊的自定義校驗方法中。
全局校驗規(guī)則注冊
自定義規(guī)則分為兩種:全局規(guī)則注冊和局部規(guī)則注冊。
全局規(guī)則是全局生效的規(guī)則,注冊之后無論是使用方法還是對象來執(zhí)行數(shù)據(jù)校驗都可以使用自定義的規(guī)則。
注冊校驗方法:
// RegisterRule registers custom validation rule and function for package.
func RegisterRule(rule string, f RuleFunc) {
customRuleFuncMap[rule] = f
}
// RegisterRuleByMap registers custom validation rules using map for package.
func RegisterRuleByMap(m map[string]RuleFunc) {
for k, v := range m {
customRuleFuncMap[k] = v
}
}您需要按照?RuleFunc?類型的方法定義,實現(xiàn)一個您需要的校驗方法,隨后使用?RegisterRule?注冊到?gvalid?模塊中全局管理。該注冊邏輯往往是在程序初始化時執(zhí)行。該方法在對數(shù)據(jù)進行校驗時將會被自動調用,方法返回?nil?表示校驗通過,否則應當返回一個非空的?error?類型值。
注意事項:自定義規(guī)則的注冊方法不支持并發(fā)調用,您需要在程序啟動時進行注冊(例如在?boot?包中處理),無法在運行時動態(tài)注冊,否則會產生并發(fā)安全問題。
示例1,訂單ID存在校驗
在電商業(yè)務中,當我們對訂單進行操作時,可以通過自定義規(guī)則校驗給定的訂單?ID?是否存在,因此我們可以注冊一個?order-exist?的全局規(guī)則來實現(xiàn)。
package main
import (
"context"
"fmt"
"github.com/GOgf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gctx"
"github.com/gogf/gf/v2/util/gvalid"
"time"
)
type Request struct {
OrderId int64
ProductName string
Amount int64
// ...
}
func init() {
rule := "order-exist"
gvalid.RegisterRule(rule, RuleOrderExist)
}
func RuleOrderExist(ctx context.Context, in gvalid.RuleFuncInput) error {
// SELECT COUNT(*) FROM `order` WHERE `id` = xxx
count, err := g.Model("order").
Ctx(ctx).
Cache(gdb.CacheOption{
Duration: time.Hour,
Name: "",
Force: false,
}).
WhereNot("id", in.Value.Int64()).
Count()
if err != nil {
return err
}
if count == 0 {
return gerror.Newf(`invalid order id "%d"`, in.Value.Int64())
}
return nil
}
func main() {
var (
ctx = gctx.New()
req = &Request{
OrderId: 65535,
ProductName: "HikingShoe",
Amount: 10000,
}
)
err := g.Validator().CheckStruct(ctx, req)
fmt.Println(err)
}
示例2,用戶唯一性規(guī)則
在用戶注冊時,我們往往需要校驗當前用戶提交的名稱/賬號是否唯一,因此我們可以注冊一個??unique-nam?e?的全局規(guī)則來實現(xiàn)。
package main
import (
"context"
"fmt"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gctx"
"github.com/gogf/gf/v2/util/gvalid"
"time"
)
type User struct {
Id int
Name string `v:"required|unique-name#請輸入用戶名稱|用戶名稱已被占用"`
Pass string `v:"required|length:6,18"`
}
func init() {
rule := "unique-name"
gvalid.RegisterRule(rule, RuleUniqueName)
}
func RuleUniqueName(ctx context.Context, in gvalid.RuleFuncInput) error {
var user *User
if err := in.Data.Scan(&user); err != nil {
return gerror.Wrap(err, `Scan data to user failed`)
}
// SELECT COUNT(*) FROM `user` WHERE `id` != xxx AND `name` != xxx
count, err := g.Model("user").
Ctx(ctx).
Cache(gdb.CacheOption{
Duration: time.Hour,
Name: "",
Force: false,
}).
WhereNot("id", user.Id).
WhereNot("name", user.Name).
Count()
if err != nil {
return err
}
if count > 0 {
if in.Message != "" {
return gerror.New(in.Message)
}
return gerror.Newf(`user name "%s" is already token by others`, user.Name)
}
return nil
}
func main() {
var (
ctx = gctx.New()
user = &User{
Id: 1,
Name: "john",
Pass: "123456",
}
)
err := g.Validator().CheckStruct(ctx, user)
fmt.Println(err)
}
局部校驗規(guī)則注冊
局部規(guī)則是僅在當前校驗對象下生效規(guī)則,校驗規(guī)則是注冊到當前使用的鏈式操作流程中而不是全局中。
注冊方法:
// RuleFunc registers one custom rule function to current Validator.
func (v *Validator) RuleFunc(rule string, f RuleFunc) *Validator
// RuleFuncMap registers multiple custom rule functions to current Validator.
func (v *Validator) RuleFuncMap(m map[string]RuleFunc) *Validator簡要介紹:
- ?
RuleFunc?方法用于注冊單個自定義校驗規(guī)則到當前對象。 - ?
RuleFuncMap?方法用于注冊多個自定義校驗規(guī)則到當前對象。
使用示例:
我們將上面其中一個例子改為局部校驗規(guī)則注冊。
package main
import (
"context"
"fmt"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gctx"
"github.com/gogf/gf/v2/util/gvalid"
"time"
)
type Request struct {
OrderId int64
ProductName string
Amount int64
// ...
}
func RuleOrderExist(ctx context.Context, in gvalid.RuleFuncInput) error {
// SELECT COUNT(*) FROM `order` WHERE `id` = xxx
count, err := g.Model("order").
Ctx(ctx).
Cache(gdb.CacheOption{
Duration: time.Hour,
Name: "",
Force: false,
}).
WhereNot("id", in.Value.Int64()).
Count()
if err != nil {
return err
}
if count == 0 {
return gerror.Newf(`invalid order id "%d"`, in.Value.Int64())
}
return nil
}
func main() {
var (
ctx = gctx.New()
req = &Request{
OrderId: 65535,
ProductName: "HikingShoe",
Amount: 10000,
}
)
err := g.Validator().RuleFunc("order-exist", RuleOrderExist).Data(req).Run(ctx)
fmt.Println(err)
} 文章標題:創(chuàng)新互聯(lián)GoFrame教程:GoFrame自定義規(guī)則-規(guī)則注冊
本文URL:http://www.dlmjj.cn/article/cdjhesp.html


咨詢
建站咨詢
