编辑单词使用PUT
方式,代表更新资源。
添加 Api
api/words/v1/words.go
type UpdateReq struct {
g.Meta `path:"words/{id}" method:"put" sm:"更新" tags:"单词"`
Id uint `json:"id" v:"required"`
Word string `json:"word" v:"required|length:1,100" dc:"单词"`
Definition string `json:"definition" v:"required|length:1,300" dc:"单词定义"`
ExampleSentence string `json:"example_sentence" v:"required|length:1,300" dc:"例句"`
ChineseTranslation string `json:"chinese_translation" v:"required|length:1,300" dc:"中文翻译"`
Pronunciation string `json:"pronunciation" v:"required|length:1,100" dc:"发音"`
ProficiencyLevel uint `json:"proficiency_level" v:"required|between:1,5" dc:"熟练度,1最低,5最高"`
}
type UpdateRes struct {
}
编写Logic
在编辑时,我们也需要检查word
是否唯一。现有的checkWord
函数不能满足需要,编辑时会连同自己一起判断,所以要改进一下:
- 加上
id
字段,不为0
时使用id
和word
联合判断; id
为0
时代表新增,仅使用word
判断。
internal/logic/words/words.go
package words
...
func Create(ctx context.Context, in *model.WordInput) error {
if err := checkWord(ctx, 0, in); err != nil {
return err
}
...
}
// checkWord 在更新时不检查自身
func checkWord(ctx context.Context, id uint, in *model.WordInput) error {
db := dao.Words.Ctx(ctx).Where("uid", in.Uid).Where("word", in.Word)
if id > 0 {
db = db.WhereNot("id", id)
}
count, err := db.Count()
if err != nil {
return err
}
if count > 0 {
return gerror.New("单词已存在")
}
return nil
}
加上更新逻辑:
internal/logic/words/words.go
package words
...
func Update(ctx context.Context, id uint, in *model.WordInput) error {
if err := checkWord(ctx, id, in); err != nil {
return err
}
db := dao.Words.Ctx(ctx).Where("uid", in.Uid).Data(do.Words{
Word: in.Word,
Definition: in.Definition,
ExampleSentence: in.ExampleSentence,
ChineseTranslation: in.ChineseTranslation,
Pronunciation: in.Pronunciation,
ProficiencyLevel: in.ProficiencyLevel,
}).Where("id", id)
if in.Uid > 0 {
db = db.Where("uid", in.Uid)
}
_, err := db.Update()
if err != nil {
return err
}
return nil
}
...
在Uid
大于零的情况下,则必须在ORM
链式中加上Uid
判断条件,以防止越权,后续的查询,删除动作同样如此。
Controller调用Logic
internal/controller/words/words_v1_update.go
package words
import (
"context"
"star/internal/logic/users"
"star/internal/logic/words"
"star/internal/model"
"star/api/words/v1"
)
func (c *ControllerV1) Update(ctx context.Context, req *v1.UpdateReq) (res *v1.UpdateRes, err error) {
uid, err := users.GetUid(ctx)
if err != nil {
return nil, err
}
err = words.Update(ctx, req.Id, &model.WordInput{
Uid: uid,
Word: req.Word,
Definition: req.Definition,
ExampleSentence: req.ExampleSentence,
ChineseTranslation: req.ChineseTranslation,
Pronunciation: req.Pronunciation,
ProficiencyLevel: model.ProficiencyLevel(req.ProficiencyLevel),
})
return nil, err
}
接口测试
$ curl -X PUT http://127.0.0.1:8000/v1/words/1 \
-H "Authorization: eyJhbGci...5U" \
-H "Content-Type: application/json" \
-d '{
"word": "example_update",
"definition": "A representative form or pattern.",
"example_sentence": "This is an example sentence.",
"chinese_translation": "例子",
"pronunciation": "ɪɡˈzɑːmp(ə)l",
"proficiency_level": 3
}'
{
"code": 0,
"message": "",
"data": null
}
执行命令,查询数据是否正常更新:
$ SELECT * FROM words;
id | uid | word | definition | example_sentence | chinese_translation | pronunciation | proficiency_level | created_at | updated_at |
---|---|---|---|---|---|---|---|---|---|
1 | 1 | example_update | A representative form or pattern. | This is an example sentence. | 例子 | ɪɡˈzɑːmp(ə)l | 3 | 2024/11/12 15:38:50 | 2024/11/12 15:38:50 |