improve RuleFunc for package gvalid

This commit is contained in:
John Guo
2021-11-09 14:31:16 +08:00
parent 814649e7a3
commit e0db3c87cf
4 changed files with 69 additions and 43 deletions

View File

@ -6,16 +6,29 @@
package gvalid
import "context"
import (
"context"
"github.com/gogf/gf/v2/container/gvar"
)
// RuleFunc is the custom function for data validation.
//
// The parameter `rule` specifies the validation rule string, like "required", "between:1,100", etc.
// The parameter `value` specifies the value for this rule to validate.
// The parameter `message` specifies the custom error message or configured i18n message for this rule.
// The parameter `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.
type RuleFunc func(ctx context.Context, rule string, value interface{}, message string, data interface{}) error
type RuleFunc func(ctx context.Context, in RuleFuncInput) error
// 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
}
var (
// customRuleFuncMap stores the custom rule functions.
@ -24,13 +37,22 @@ var (
)
// RegisterRule registers custom validation rule and function for package.
// It returns error if there's already the same rule registered previously.
func RegisterRule(rule string, f RuleFunc) error {
customRuleFuncMap[rule] = f
return nil
}
// DeleteRule deletes custom defined validation rule and its function from global package.
func DeleteRule(rule string) {
delete(customRuleFuncMap, rule)
// RegisterRuleByMap registers custom validation rules using map for package.
func RegisterRuleByMap(m map[string]RuleFunc) error {
for k, v := range m {
customRuleFuncMap[k] = v
}
return nil
}
// DeleteRule deletes custom defined validation one or more rules and associated functions from global package.
func DeleteRule(rules ...string) {
for _, rule := range rules {
delete(customRuleFuncMap, rule)
}
}

View File

@ -8,6 +8,7 @@ package gvalid
import (
"context"
"github.com/gogf/gf/v2/container/gvar"
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/text/gstr"
@ -133,7 +134,12 @@ func (v *Validator) doCheckValue(ctx context.Context, input doCheckValueInput) E
if customRuleFunc != nil {
// It checks custom validation rules with most priority.
message := v.getErrorMessageByRule(ctx, ruleKey, customMsgMap)
if err := customRuleFunc(ctx, ruleItems[index], input.Value, message, input.DataRaw); err != nil {
if err := customRuleFunc(ctx, RuleFuncInput{
Rule: ruleItems[index],
Message: message,
Value: gvar.New(input.Value),
Data: gvar.New(input.DataRaw),
}); err != nil {
match = false
errorMsgArray[ruleKey] = err.Error()
} else {

View File

@ -127,17 +127,17 @@ func ExampleRegisterRule() {
}
rule := "unique-name"
gvalid.RegisterRule(rule, func(ctx context.Context, rule string, value interface{}, message string, data interface{}) error {
gvalid.RegisterRule(rule, func(ctx context.Context, in gvalid.RuleFuncInput) error {
var (
id = data.(*User).Id
name = gconv.String(value)
id = in.Data.Val().(*User).Id
name = gconv.String(in.Value)
)
n, err := g.Model("user").Where("id != ? and name = ?", id, name).Count()
if err != nil {
return err
}
if n > 0 {
return errors.New(message)
return errors.New(in.Message)
}
return nil
})
@ -149,8 +149,8 @@ func ExampleRegisterRule() {
func ExampleRegisterRule_OverwriteRequired() {
rule := "required"
gvalid.RegisterRule(rule, func(ctx context.Context, rule string, value interface{}, message string, data interface{}) error {
reflectValue := reflect.ValueOf(value)
gvalid.RegisterRule(rule, func(ctx context.Context, in gvalid.RuleFuncInput) error {
reflectValue := reflect.ValueOf(in.Value.Val())
if reflectValue.Kind() == reflect.Ptr {
reflectValue = reflectValue.Elem()
}
@ -171,7 +171,7 @@ func ExampleRegisterRule_OverwriteRequired() {
isEmpty = reflectValue.Len() == 0
}
if isEmpty {
return errors.New(message)
return errors.New(in.Message)
}
return nil
})

View File

@ -12,8 +12,6 @@ import (
"testing"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/test/gtest"
"github.com/gogf/gf/v2/util/gvalid"
)
@ -22,14 +20,14 @@ func Test_CustomRule1(t *testing.T) {
rule := "custom"
err := gvalid.RegisterRule(
rule,
func(ctx context.Context, rule string, value interface{}, message string, data interface{}) error {
pass := gconv.String(value)
func(ctx context.Context, in gvalid.RuleFuncInput) error {
pass := in.Value.String()
if len(pass) != 6 {
return errors.New(message)
return errors.New(in.Message)
}
m := gconv.Map(data)
m := in.Data.Map()
if m["data"] != pass {
return errors.New(message)
return errors.New(in.Message)
}
return nil
},
@ -71,10 +69,10 @@ func Test_CustomRule1(t *testing.T) {
func Test_CustomRule2(t *testing.T) {
rule := "required-map"
err := gvalid.RegisterRule(rule, func(ctx context.Context, rule string, value interface{}, message string, data interface{}) error {
m := gconv.Map(value)
err := gvalid.RegisterRule(rule, func(ctx context.Context, in gvalid.RuleFuncInput) error {
m := in.Value.Map()
if len(m) == 0 {
return errors.New(message)
return errors.New(in.Message)
}
return nil
})
@ -115,12 +113,12 @@ func Test_CustomRule2(t *testing.T) {
func Test_CustomRule_AllowEmpty(t *testing.T) {
rule := "allow-empty-str"
err := gvalid.RegisterRule(rule, func(ctx context.Context, rule string, value interface{}, message string, data interface{}) error {
s := gconv.String(value)
err := gvalid.RegisterRule(rule, func(ctx context.Context, in gvalid.RuleFuncInput) error {
s := in.Value.String()
if len(s) == 0 || s == "gf" {
return nil
}
return errors.New(message)
return errors.New(in.Message)
})
gtest.Assert(err, nil)
// Check.
@ -160,13 +158,13 @@ func Test_CustomRule_AllowEmpty(t *testing.T) {
func TestValidator_RuleFunc(t *testing.T) {
ruleName := "custom_1"
ruleFunc := func(ctx context.Context, rule string, value interface{}, message string, data interface{}) error {
pass := gconv.String(value)
ruleFunc := func(ctx context.Context, in gvalid.RuleFuncInput) error {
pass := in.Value.String()
if len(pass) != 6 {
return errors.New(message)
return errors.New(in.Message)
}
if m := gconv.Map(data); m["data"] != pass {
return errors.New(message)
if m := in.Data.Map(); m["data"] != pass {
return errors.New(in.Message)
}
return nil
}
@ -214,13 +212,13 @@ func TestValidator_RuleFunc(t *testing.T) {
func TestValidator_RuleFuncMap(t *testing.T) {
ruleName := "custom_1"
ruleFunc := func(ctx context.Context, rule string, value interface{}, message string, data interface{}) error {
pass := gconv.String(value)
ruleFunc := func(ctx context.Context, in gvalid.RuleFuncInput) error {
pass := in.Value.String()
if len(pass) != 6 {
return errors.New(message)
return errors.New(in.Message)
}
if m := gconv.Map(data); m["data"] != pass {
return errors.New(message)
if m := in.Data.Map(); m["data"] != pass {
return errors.New(in.Message)
}
return nil
}