引言:
在完成了对管理员登录功能的简单实现后,接下来围绕文章和标签两张表的crud进行操作。
一:文章表的crud
首先完善新增文章操作
controller层
仿照参考文档中的代码,为/controller/article/article_v1_article_create.go编写代码
func (c *ControllerV1) ArticleCreate(ctx context.Context, req *v1.ArticleCreateReq) (res *v1.ArticleCreateRes, err error) {
err = service.Article().Create(ctx, model.ArticleCreateInput{
Content: req.Content,
Layout: req.Layout,
PostName: req.PostName,
Tags: req.Tags,
Title: req.Title,
TagsId: req.TagsId,
})
return
}
解决报红的三个地方,在model层中创建article.go,定义ArticleCreateInput结构体,目的是为了定义统一的入参结构,具体如何理解个人参考的是这篇文章GoFrame V2真香,我是Get到了高内聚低耦合的点,你呢?_Go_王中阳Go_InfoQ写作社区
ArticleCreateInput如下
type ArticleCreateInput struct {
Content string
Layout string
PostName string
Tags string
Title string
Post int
TagsId string
}
接下来因为要使用logic来生成service接口,所以先编写logic层的代码
logic层
在/logic/article下创建article.go
type (
sArticle struct {
}
)
func init() {
service.RegisterArticle(New())
}
func New() service.IArticle { return &sArticle{} }
func (s *sArticle) Create(ctx context.Context, in model.ArticleCreateInput) (err error) {
if in.Title == "" {
return err
}
if in.Content == "" {
return err
}
return dao.Article.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
_, err := dao.Article.Ctx(ctx).Data(do.Article{
Content: in.Content,
Layout: in.Layout,
Post: in.Post,
PostName: in.PostName,
TagsId: in.TagsId,
Title: in.Title,
}).Insert()
return err
})
}
由于我goLand配置了官方给的自动配置模块规范-gen service - GoFrame (ZH)-Latest - GoFrame官网 - 类似PHP-Laravel, Java-SpringBoot的Go企业级开发框架
因此编写完成后无需手动输入gf gen service。
后来在测试前发现了数据库的create_time和update_time自己设置了不能为空,于是在插入语句中新增两句
CreateTime: gtime.New(time.Now()),
UpdateTime: gtime.New(time.Now()),
检查数据库,数据库中也成功插入数据
这样一个基本的新增操作就完成了
删除数据
这里采用逻辑删除,也就是软删除,所以本质上也就是update。以deleteTime是否为空作为判断是否删除的标准.
步骤和上面的操作一样
先检查api接口
package v1
import "github.com/gogf/gf/v2/frame/g"
type ArticleDeleteReq struct {
g.Meta `path:"/article/delete" tags:"Article" method:"post" summary:"删除文章"`
Id int `p:"id" v:"required#文章ID不能为空" dc:"文章ID"`
}
type ArticleDeleteRes struct {
}
然后在controller对应的包下编写代码
package article
import (
"context"
"demo-blog/internal/model"
"demo-blog/internal/service"
"demo-blog/api/article/v1"
)
func (c *ControllerV1) ArticleDelete(ctx context.Context, req *v1.ArticleDeleteReq) (res *v1.ArticleDeleteRes, err error) {
err = service.Article().Delete(ctx, model.ArticleDeleteInput{
Id: req.Id,
})
return
}
在model层创建ArticleDeleteInput结构体
type ArticleDeleteInput struct {
Id int
}
最后在logic层的article/article.go中编写
Transaction是添加事务管理
func (s *sArticle) Delete(ctx context.Context, in model.ArticleDeleteInput) (err error) {
return dao.Article.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
_, err := dao.Article.Ctx(ctx).Where("id", in.Id).Update(do.Article{
DeleteTime: gtime.New(time.Now()),//为输入id对应的那条数据更新delete_time
})
return err
})
}
在之后的所有查询里,都要添加上判断delete_time是否为空的条件。比较麻烦,但是goframe有解决的方案:ORM链式操作-时间维护 - GoFrame (ZH)-Latest - GoFrame官网 - 类似PHP-Laravel, Java-SpringBoot的Go企业级开发框架
只不过只能在它的链式操作中使用,并且数据库要包含create_at,update_at,delete_at任意或多个字段时才启用。
现在重新运行一下项目
测试接口
别忘了在业务层或控制层对输入的内容进行判断,确保输入数据符合要求。
可以看到成功的为这条字段更新了删除时间,删除操作也完成了。
查询操作
默认写分页查询。
分页查询可参考官方文档ORM查询-ScanAndCount - GoFrame (ZH)-Latest - GoFrame官网 - 类似PHP-Laravel, Java-SpringBoot的Go企业级开发框架
总结:
api层用于处理接收的参数
model层用于控制传入的数据标准
controller层将得到的数据传入业务层
logic层处理具体的业务逻辑