Egg.js 并不自带 ORM,这篇文章将向你介绍如何在 Egg 中使用 Modelar ORM。
Modelar 非常容易使用,因此你不需要向 sequelize 那样要封装一个 egg-sequelize 模块 才能使用,直接使用就好。
首先,你需要创建一个项目,名称例如 egg-modelar
。
mkdir egg-modelar
cd egg-modelar
npm init
npm install egg
npm install egg-bin
npm install modelar
然后按照 Eggjs 官网所介绍的,在生成的 package.json
中添加下面的 script
命令
// package.json
{
"name": "egg-modelar",
"scripts": {
"dev": "egg-bin dev"
}
}
然后,先创建一个默认配置文件,来设置 cookie 密钥并关闭 csrf 检测(测试需要)。文件名为
config/config.default.js
,内容为:
// config/config.default.js
exports.keys = "my-cookie";
exports.security = {
csrf: {
enable: false,
},
};
接下来,我们需要扩展一下 context
对象,将一个在数据库对象绑定在整个请求过程中。
// extend/context.js
const { DB } = require("modelar"); // npm install modelar
module.exports = {
get db(){
if (!this.db) {
this.db = new DB({
type: "mysql",
database: "modelar",
host: "127.0.0.1",
port: 3306,
user: "root",
password: "161301"
});
}
return this.db;
}
};
另外,还需要在响应发送给客户端之后,自动回收数据库连接。创建一个名为
middleware/releasedb.js
的文件,内容如下:
// middleware/releasedb.js
module.exports = options => {
return async (ctx, next) => {
// 添加一个事件处理器,当响应被发送回客户端后,回收数据库连接并等待下一个请求
// 取回它。
ctx.res.on("finish", () => {
ctx.db.release();
});
await next();
}
};
并在 config.default.js
中加入下面这一行内容
exports.middleware = ["releasedb"];
接下来,我们创建一个 Article
模型,用来管理文章。文件名为 model/article.js
,
内容为:
// model/article.js
const { Model } = require("modelar");
module.exports = class Article extends Model{
constructor(data = {}) {
super(data, {
table: "articles",
primary: "id",
fields: ["id", "title", "content"],
searchable: ["title", "content"]
});
}
};
然后,在控制器中使用它。创建一个新的控制器 app/controller/article.js
,内容如下:
// app/controller/article.js
const { Controller } = require('egg');
const { Table } = require("modelar");
const Article = require("../model/article");
module.exports = class extends Controller {
/** 创建一个名称为 articles 的表 */
async createTable() {
const { ctx } = this;
ctx.status = 200;
try {
var table = new Table("articles");
table.addColumn("id").primary().autoIncrement();
table.addColumn("title", "varchar", 255).notNull();
table.addColumn("content", "varchar", 1024).notNull();
// 保存表并向客户端返回消息
table = await table.use(ctx.db).save();
ctx.body = {
success: true,
data: "数据表创建成功!",
};
} catch (e) {
ctx.body = {
success: false,
msg: e.message,
};
}
}
/** 创建一个篇新文章 */
async create() {
const { ctx } = this;
ctx.status = 200;
try {
var article = new Article;
article.title = "A new article in Modelar circumstance.";
article.content = "This is the content of the article.";
// 保存用户并向客户端返回消息
article = await article.use(ctx.db).save();
ctx.body = {
success: true,
data: article,
};
} catch (e) {
ctx.body = {
success: false,
msg: e.message,
};
}
}
/** 获取用户 */
async get() {
const { ctx } = this;
ctx.status = 200;
try {
var article = await Article.use(ctx.db).get(ctx.params.id);
ctx.body = {
success: true,
data: article,
};
} catch (e) {
ctx.body = {
success: false,
msg: e.message,
};
}
}
}
并在 app/router.js
文件中为控制器分配路由地址:
// app/router.js
module.exports = app => {
const { router, controller } = app;
router.post('/article/create-table', controller.article.createTable);
router.post("/article/create", controller.article.create);
router.get("/article/:id", controller.article.get);
};
最后启动服务器来进行测试:
npm run dev
推荐使用可视化的工具,如 Chrome 的 RESTED
插件来模拟请求。
赞一个,不过看了下,还是要封装个插件才更友好,如 releasedb
这个如果是必备的,就应该在插件里面自动挂载,不应该给到应用开发者去搞
@atian25 你去封装吧,我不是很了解 eggjs 的插件机制,我不是用 eggjs 的
我这边没使用场景,留给有需要的社区开发者吧