使用 strapi 快速构建 API 和 CMS 管理系统
最近创建了一个公众号,欢迎大家关注,一起学习交流。
# 前言
作为一个合格的前端工程师,怎么能够不懂得自己写后端接口呢?会自己写后端API接口,能够在工作当中有效的提供工作竞争力,还能够帮我有效的提高工作效率。有的同学说,我会 Node.js,确实使用 Node.js 帮助前端工程师晋升为全栈 。
但是在一些普通的增删改查都要自己亲自动手去写,那效率着实是大打折扣的。strapi 就是一款能够快速上手,让一个懂一点 Node.js 的前端开发就能够快速的开发出增删改查的接口来,最近刚好有使用到 strapi 作为网站的后端,刚好在这里记录一下自己学习的过程。
# 快速上手
strapi 官网:https://strapi.io/ (opens new window)
在开始使用之前我们需要确保自己的 Node.js 版本为 v14
、v16
或者 v18
,npm 的版本为 v6
,如果需要使用到 SQLite 作为数据库的话,还需要在自己的电脑上安装 Python。
# 安装 strapi
直接使用官方提供的快速开始的模版,这里我使用 TypeScript 的模版,命令如下:
npx create-strapi-app@latest my-api --quickstart --ts
如果一切顺利,创建好工程之后,将会自动进行依赖的安装,并且安装之后会自动运行,我们可以在终端当中看到如下的提示:
自动打开浏览器之后,可以看到下面的页面,提示我们创建一个超级管理员的身份,输入自己的账号和密码,目前界面显示的是英文,稍后我们进行配置接口让其显示中文界面。
注册输入一个账号、邮箱、密码,点击 Let's start
,进入到即可进入到 CMS 系统当中。
# 修改 strapi 管理界面为中文
接下来我们进行项目代码的配置,将界面设置为中文,使用自己熟悉的开发工具打开工程,这里我使用 VSCode,项目的结构如下图所示:
这里我使用了文件折叠的插件,才让下面那些配置文件显示成层级结构的,不用管,将 src/admin/app.example.tsx
修改为 src/admin/app.tsx
,并将代码修改成如下:
export default {
config: {
locales: [
'zh-Hans',
'zh',
],
},
bootstrap(app) {
console.log(app);
},
};
2
3
4
5
6
7
8
9
10
11
保存代码,项目会自动重启,打开管理系统,找到 Settings -> internationalization -> Add new locale
,添加一个中文的语言设置,如下图所示:
点击 save
保存语言配置项,然后重启一下项目,再次登录到管理系统当中。点击左下角的头像,选择 Profile
,跳转到个人信息设置页面,可以看到有设置中文的选项了,我们选中中文(简体)
,然后点击 save
,即可看到界面切换到中文。
如果你阅读到这里,恭喜你马上就能够发现原来开发一个接口这么容易。
# 快速开发一套 CRUD 接口
# 创建模型
这里我就拿项目当中最常用的用户管理来说,首先我们需要一个用户表,点击 模型构建器
,可以看到已经有一个 User 的集合类型,这个是 strapi 自己提供的,我们当前登录的用户的数据就存储在这个模型当中,但是这个不是我们所需要的,新增一个集合类型 UserProfile
,注意高级设置
当中的 Draft & publish
根据实际需要进行勾选,勾选之后新增加的数据需要手动进行发布才能生效,这里我就取消勾选了。
创建完模型之后,点击添加一个字段
,选择 文本
,设置名称为 username
,选择 较短的文本
,高级设置当中的类型选择 必须
和 唯一
的,其他的我们暂时用不到,实际中可以根据需要选择。
然后依次创建 password
、sex
、nickName
、phone
、email
等等,根据实际需要自己添加。然后点击 保存
,项目将自动重启。
名称 | 类型 |
---|---|
username | 文本、必填、唯一 |
password | 密码框 |
sex | 枚举 |
nickName | 文本 |
phone | 文本 |
电子邮箱 |
重启完毕,就可以在内容管理当中看到 集合类型
当中看到 UserProfile
,然后我们创建几条记录。
# 对外暴露接口
接下来我们对外暴露接口,让我们自己编写的前端用户使用,找到 设置 -> 角色列表 -> Public
,进行编辑,将 find
和 findOne
接口勾选,然后点击 保存
,进行勾选的时候,旁边的 绑定路由到 api::user-profile.user-profile
下面的 /api/user-profiles
就是 strapi 为我们自动生成的接口。
我们复制到浏览器上使用一下,拼接上域名和端口
http://localhost:1337/api/user-profiles
可以看到接口已经返回了 json 数据,我们添加到 CMS 当中的内容已经成功返回。
strapi 也提供了各种各样的筛选条件,比如使用 filters[username]=xxx
可以筛选出 username 为 xxx 的数据,更多筛选条件可以查看官方文档,文档地址: https://docs.strapi.io/dev-docs/api/rest (opens new window)
http://localhost:1337/api/user-profiles?filters[username]=xiao
strapi 也提供非常丰富的插件,比如要使用 GraphQL,直接安装 GraphQL 插件即可。
# 自定义 API 接口
有了前面的编写经验,相信能够阅读到这里的你,应该已经迫不接待想要自己使用 strapi 编写自己的接口了吧。
strapi 是在 koa 的基础上开发来的,我们可以通过设置,实现自己的业务逻辑,下面就用一个用户注册的接口来介绍一下使用 strapi 编写自定义业务逻辑的接口。
# 实战用户注册接口
通过 strapi 我们已经得到了 user-profile
相关的增删改查 API 接口,但是在实际业务开发当中,不可能只有这种简单的增删改查接口,这里我带领大家实现一个用户注册的接口。
# 1、制定前后端接口交换的数据格式
直接采用最简单的方式,我们规定前端请求我们的接口的参数如下:
{
"username": "test-admin",
"password": "12345",
"nickName": "dimples",
"phone": "15555555555",
"email": "2890841438@qq.com"
}
2
3
4
5
6
7
包含了2个字段,username
和 password
,规定后端接口的地址为 /api/user-reg
,请求后端接口之后返回我们需要的登录态,这里的登录态我们是用 jwt
。
# 2、编码
已经明白了我们需要开发的接口之后,下面直接进入编码阶段,在 user-profile
的 routes
下面新增一个 register.ts
文件,方便将用户的请求映射到我们自己的 controller
上。
register.ts
当中的代码如下所示,直接导出一个包含 routes
数组默认对象,数组当中指定了注册的请求路径和相应的 handler
,这里的 handler
指示的是工程目录下的 controller
,当中的 user-profile.ts
当中的 index
方法:
// register.ts
export default {
routes: [
{
method: 'POST',
path: '/user-reg',
handler: 'user-profile.register',
},
]
}
2
3
4
5
6
7
8
9
10
在开发实际业务接口之前,因为使用到 md5
对用户的密码进行加密,我们需要先安装几个需要用到的包,命令如下:
npm install md5
npm install @types/md5 -D
加下来编写我们的业务代码,user-profile.ts
当中的代码如下所示, 在 strapi
为我们创建好的 controller
之上增加我们自己的 :
/**
* user-profile controller
*/
import { factories } from "@strapi/strapi";
import md5 from "md5";
export default factories.createCoreController(
"api::user-profile.user-profile",
({ strapi }) => ({
async register(ctx) {
const UserProfileModel = strapi.db.query(
"api::user-profile.user-profile"
);
const { username, password, nickName, phone, email } = ctx.request.body;
const user = await UserProfileModel.findOne({
where: {
$or: [
{
username,
},
{
phone,
},
{
email,
},
],
},
});
// 如果用户已经存在了就提示已经注册
if (user) {
return {
msg: "用户已经注册过了",
code: 4000,
data: null,
};
}
// 注册
const result = await UserProfileModel.create({
select: ["username", "nickName", "phone", "email"],
data: {
username,
password: md5(password),
nickName,
phone,
email,
},
});
return {
msg: "注册成功",
data: result,
code: 2000,
};
},
})
);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
到这里为止,我们的业务代码已经编写好了,但是代码有些太长了,实际开发当中我们应该将业务单独抽离出去,不应该将业务代码编写在 controller
当中。
# 3、测试
我们的代码已经编写完成了,接下来我们对接口进行测试,首先我们需要在后台将我们编写的 register
接口开放给公共用户进行调用,如下图:
这里我直接使用 ApiFox
,新建接口进行测试,制造一些假数据再请求接口,发现和我们编写的业务逻辑一致,当 username
、phone
、email
唯一的时候,成功注册,并且返回用户的注册信息。