1
0
mirror of https://github.com/astaxie/beego.git synced 2024-11-25 21:51:28 +00:00

Merge pull request #1543 from miraclesu/validation

Add validation custom function
This commit is contained in:
astaxie 2016-01-07 23:24:31 +08:00
commit 43ca13b516
4 changed files with 100 additions and 7 deletions

View File

@ -41,7 +41,7 @@ Direct Use:
}
}
// or use like this
if v := valid.Max(u.Age, 140); !v.Ok {
if v := valid.Max(u.Age, 140, "ageMax"); !v.Ok {
log.Println(v.Error.Key, v.Error.Message)
}
}
@ -63,7 +63,48 @@ Struct Tag Use:
}
func main() {
valid := Validation{}
valid := validation.Validation{}
u := user{Name: "test", Age: 40}
b, err := valid.Valid(u)
if err != nil {
// handle error
}
if !b {
// validation does not pass
// blabla...
}
}
Use custom function:
import (
"github.com/astaxie/beego/validation"
)
type user struct {
Id int
Name string `valid:"Required;IsMe"`
Age int `valid:"Required;Range(1, 140)"`
}
func IsMe(v *validation.Validation, obj interface{}, key string) {
name, ok:= obj.(string)
if !ok {
// wrong use case?
return
}
if name != "me" {
// valid false
v.SetError("Name", "is not me!")
}
}
func main() {
valid := validation.Validation{}
if err := validation.AddCustomFunc("IsMe", IsMe); err != nil {
// hadle error
}
u := user{Name: "test", Age: 40}
b, err := valid.Valid(u)
if err != nil {

View File

@ -56,6 +56,27 @@ func init() {
}
}
type CustomFunc func(v *Validation, obj interface{}, key string)
// Add a custom function to validation
// The name can not be:
// Clear
// HasErrors
// ErrorMap
// Error
// Check
// Valid
// NoMatch
// If the name is same with exists function, it will replace the origin valid function
func AddCustomFunc(name string, f CustomFunc) error {
if unFuncs[name] {
return fmt.Errorf("invalid function name: %s", name)
}
funcs[name] = reflect.ValueOf(f)
return nil
}
// ValidFunc Valid function type
type ValidFunc struct {
Name string
@ -102,7 +123,6 @@ func getValidFuncs(f reflect.StructField) (vfs []ValidFunc, err error) {
return
}
if vfs, tag, err = getRegFuncs(tag, f.Name); err != nil {
fmt.Printf("%+v\n", err)
return
}
fs := strings.Split(tag, ";")
@ -214,7 +234,7 @@ func trim(name, key string, s []string) (ts []interface{}, err error) {
for i := 0; i < len(s); i++ {
var param interface{}
// skip *Validation and obj params
if param, err = magic(fn.Type().In(i+2), strings.TrimSpace(s[i])); err != nil {
if param, err = parseParam(fn.Type().In(i+2), strings.TrimSpace(s[i])); err != nil {
return
}
ts[i] = param
@ -224,7 +244,7 @@ func trim(name, key string, s []string) (ts []interface{}, err error) {
}
// modify the parameters's type to adapt the function input parameters' type
func magic(t reflect.Type, s string) (i interface{}, err error) {
func parseParam(t reflect.Type, s string) (i interface{}, err error) {
switch t.Kind() {
case reflect.Int:
i, err = strconv.Atoi(s)

View File

@ -38,7 +38,7 @@
// }
// }
// // or use like this
// if v := valid.Max(u.Age, 140); !v.Ok {
// if v := valid.Max(u.Age, 140, "ageMax"); !v.Ok {
// log.Println(v.Error.Key, v.Error.Message)
// }
// }

View File

@ -46,6 +46,38 @@ var MessageTmpls = map[string]string{
"ZipCode": "Must be valid zipcode",
}
// set default messages
// if not set, the default messages are
// "Required": "Can not be empty",
// "Min": "Minimum is %d",
// "Max": "Maximum is %d",
// "Range": "Range is %d to %d",
// "MinSize": "Minimum size is %d",
// "MaxSize": "Maximum size is %d",
// "Length": "Required length is %d",
// "Alpha": "Must be valid alpha characters",
// "Numeric": "Must be valid numeric characters",
// "AlphaNumeric": "Must be valid alpha or numeric characters",
// "Match": "Must match %s",
// "NoMatch": "Must not match %s",
// "AlphaDash": "Must be valid alpha or numeric or dash(-_) characters",
// "Email": "Must be a valid email address",
// "IP": "Must be a valid ip address",
// "Base64": "Must be valid base64 characters",
// "Mobile": "Must be valid mobile number",
// "Tel": "Must be valid telephone number",
// "Phone": "Must be valid telephone or mobile phone number",
// "ZipCode": "Must be valid zipcode",
func SetDefaultMessage(msg map[string]string) {
if len(msg) == 0 {
return
}
for name := range msg {
MessageTmpls[name] = msg[name]
}
}
// Validator interface
type Validator interface {
IsSatisfied(interface{}) bool
@ -556,7 +588,7 @@ func (b Base64) GetLimitValue() interface{} {
}
// just for chinese mobile phone number
var mobilePattern = regexp.MustCompile("^((\\+86)|(86))?(1(([35][0-9])|[8][0-9]|[7][067]|[4][579]))\\d{8}$")
var mobilePattern = regexp.MustCompile("^((\\+86)|(86))?(1(([35][0-9])|[8][0-9]|[7][0679]|[4][579]))\\d{8}$")
// Mobile check struct
type Mobile struct {