业务逻辑封装
基本介绍
职责划分
所有的业务逻辑实现均封装于service
层中,不推荐实现于控制器api
中。service
层之间的包存在相互调用,不推荐api
在代码层级相互调用。
数据校验
针对于注册逻辑,参数结构体以及校验规则的绑定并没有放置于控制器中,而是由service
负责维护。因为该方法的参数复杂且复用性比较强,不仅仅在控制中需要校验,其他service
调用时也需要执行该校验逻辑。
// 注册输入参数
type SignUpInput struct {
Passport string `v:"required|length:6,16#账号不能为空|账号长度应当在:min到:max之间"`
Password string `v:"required|length:6,16#请输入确认密码|密码长度应当在:min到:max之间"`
Password2 string `v:"required|length:6,16|same:Password#密码不能为空|密码长度应当在:min到:max之间|两次密码输入不相等"`
Nickname string
}
针对参数比较复杂且后续可能会变动的参数,推荐定义并使用结构体作为输入参数。
实现代码
https://github.com/gogf/gf-demos/blob/master/app/service/user/user.go
package user
import (
"errors"
"fmt"
"github.com/gogf/gf-demos/app/model/user"
"github.com/gogf/gf/net/ghttp"
"github.com/gogf/gf/os/gtime"
"github.com/gogf/gf/util/gconv"
"github.com/gogf/gf/util/gvalid"
)
const (
USER_SESSION_MARK = "user_info"
)
// 注册输入参数
type SignUpInput struct {
Passport string `v:"required|length:6,16#账号不能为空|账号长度应当在:min到:max之间"`
Password string `v:"required|length:6,16#请输入确认密码|密码长度应当在:min到:max之间"`
Password2 string `v:"required|length:6,16|same:Password#密码不能为空|密码长度应当在:min到:max之间|两次密码输入不相等"`
Nickname string
}
// 用户注册
func SignUp(data *SignUpInput) error {
// 输入参数检查
if e := gvalid.CheckStruct(data, nil); e != nil {
return errors.New(e.String())
}
// 昵称为非必需参数,默认使用账号名称
if data.Nickname == "" {
data.Nickname = data.Passport
}
// 账号唯一性数据检查
if !CheckPassport(data.Passport) {
return errors.New(fmt.Sprintf("账号 %s 已经存在", data.Passport))
}
// 昵称唯一性数据检查
if !CheckNickName(data.Nickname) {
return errors.New(fmt.Sprintf("昵称 %s 已经存在", data.Nickname))
}
// 将输入参数赋值到数据库实体对象上
var entity *user.Entity
if err := gconv.Struct(data, &entity); err != nil {
return err
}
// 记录账号创建/注册时间
entity.CreateTime = gtime.Now()
if _, err := user.Save(entity); err != nil {
return err
}
return nil
}
// 判断用户是否已经登录
func IsSignedIn(session *ghttp.Session) bool {
return session.Contains(USER_SESSION_MARK)
}
// 用户登录,成功返回用户信息,否则返回nil; passport应当会md5值字符串
func SignIn(passport, password string, session *ghttp.Session) error {
one, err := user.FindOne("passport=? and password=?", passport, password)
if err != nil {
return err
}
if one == nil {
return errors.New("账号或密码错误")
}
return session.Set(USER_SESSION_MARK, one)
}
// 用户注销
func SignOut(session *ghttp.Session) error {
return session.Remove(USER_SESSION_MARK)
}
// 检查账号是否符合规范(目前仅检查唯一性),存在返回false,否则true
func CheckPassport(passport string) bool {
if i, err := user.FindCount("passport", passport); err != nil {
return false
} else {
return i == 0
}
}
// 检查昵称是否符合规范(目前仅检查唯一性),存在返回false,否则true
func CheckNickName(nickname string) bool {
if i, err := user.FindCount("nickname", nickname); err != nil {
return false
} else {
return i == 0
}
}
// 获得用户信息详情
func GetProfile(session *ghttp.Session) (u *user.Entity) {
_ = session.GetStruct(USER_SESSION_MARK, &u)
return
}