环境搭建
创建目录 mkdir <dir>&&cd <dir>
构建项目 npm init egg
按提示选择安装
选择需要的模板新建项目
安装依赖 npm install
学习笔记
路由
目录一览
router
注册路由
router.get('/admin/:id',controller.home.index)
get是路由的方法,home是控制器里的文件名,index是注册的哈希地址
ctx
获取路由get传值的参数
ctx.params
获取url的问号get方式传值参数
ctx.query
响应体
ctx.body
状态码
ctx.status
获取数据ctx.request.body
获取路由参数
router.get('/user/:id',controller.user.index)
的参数id会传递给ctx.params路由中?传递的参数会传递到ctx.query对象里
资源路由(语法糖)
//app/router.js module.exports=app=>{ const {router, controller}=app; router.resources('post','/api/posts',controller.posts) //第二个参数为访问前缀 //router.resources('users','/api/v1/users',controller.v1.users) } //app/controller/posts.js async index(){} async new(){} async create(){} async show(){} async edit(){} async update(){} async destroy(){}
路由分组
//app/router.js module.exports=app=>{ require('./router/news')(app) require('./router/admin')(app) } //app/router/news.js module.exports=app=>{ const {router}=app router.get('/news/list',app.controller.news.list) router.get('/news/detail',app.controller.news.detail) } //app/admin.js module.exports=app=>{ app.router.get('/news/user',app.controller.admin.usuer) app.router.get('/news/log',app.controller.admin.log) }
数据库
安装插件
npm install -S egg-sequelize mysql2
引入插件config/plugin.js
exports.sequelize={ enable: true package: 'egg-sequelize' }
配置数据库config/config.default.js
config.sequelize={ dialect:'mysql', host: '127.0.0.1', usernamew:'root', password:'root', port:3306, database:'eggapi', timezone:'+08:00', define:{ freezeTableName:true, //取消数据表名复数 timestamps:true, //自动写入时间戳 paranoid:true, //字段生成软时间戳 createdAt:'created_at', updatedAt:'updated_at', deletedAt:'deleted_at', underscored:true //驼峰命名 } }
sequelize提供了sequelize-cli来实现Migrations,可以引入
npm install -D sequelize-cli
创建并配置.sequelizerc文件
'use strict' const path =require('path') module.exports={ config:path.join(__dirname,'database/config.json'), 'migrations-path':path.join(__dirname,'database/migrations'), 'seeders-path':path.join(__dirname,'database/seeders'), 'models-path':path.join(__dirname,'database/model'), }
初始化Migrations配置文件和目录
npx sequelize init:config npx sequelize init:migrations // npx sequelize init:models
修改生成的database/config.json文件和database/migrations目录
{ "development":{ "username":"root" "password":null "database":"eggapi" "host":"127.0.0.1" "dialect":"mysql" "iimezone":"+08:00" } }
创建数据库
npx sequelize db:create
数据库迁移
创建数据迁移表npx sequelize migration:generate --name=init-user
database/migrations/目录下生成数据表迁移文件xxxx-init-user.js,然后定义
'use strict' module.exports={ up:aysnc(queryInterface,Sequelize)=>{ const {INITEGER,STRING,DATE,ENUM}=Sequelize //创建表 await queryInterface.createTable('user',{ id:{type:STRING(20).UNSIGNED,primaryKey:true,autoIncrement:true}, username:{type:STRING(200),allowNull:false,defaultValue:'',comment:'用户名称',unique:true}, password:{type:STRING(200),allowNull:false,defaultValue:''}, avatar_url:{type:STRING(20),allowNull:true,defaultValue:''}, username:{type:ENUM,values:['男','女','保密'],allowNull:true,defaultValue:'男',comment:'用户性别'}, created_at:DATE, updated_at:DATE }) } down:aysnc queryInterface+>{ await queryInterface.dropTable('user') } }
执行migrate进行数据库变更
# 升级数据库 npx sequelize db:migrate # 回滚 #npx sequelize db:migrate:undo #回退初始状态 #npx sequelize db:migrate:undo:all
模型(好奇为啥不直接用SQL语句)
创建模型/app/model/user.js
'use strict' module.expoets=app=>{ const {STRING, INTEGER, DATE,ENUM}=app.Sequelize const User = app.model.define('user'),{ id:{type:STRING(20).UNSIGNED,primaryKey:true,autoIncrement:true}, username:{type:STRING(200),allowNull:false,defaultValue:'',comment:'用户名称',unique:true}, password:{type:STRING(200),allowNull:false,defaultValue:'',set(val){this.setDataValue('password',val*10)}}, //修改器(可用于加密) avatar_url:{type:STRING(20),allowNull:true,defaultValue:''}, username:{type:ENUM,values:['男','女','保密'],allowNull:true,defaultValue:'男',comment:'用户性别'}, created_at:DATE, updated_at:DATE },{ timestamps:true, tableName:'user' } return User }
创建用户
//app/router/user.js async create(){ //增加数据 //const res=await this.app.model.User.create({ // username:this.ctx.request.body.username, // password:this.ctx.request.body.password, // sex:this.ctx.request.body.sex //}) //批量增加 const res=await this.app.model.User.bulkCreate([{ username:'test1', password:'12345678', sex:'保密' },{ username:'test2', password:'12345678', sex:'保密' },{ username:'test3', password:'12345678', sex:'保密' },{ username:'test4', password:'12345678', sex:'保密' }]) // }
查询用户
//app/router/user.js async read(){ //主键查询 const detail=await this.app.model.User.findByPk(this.ctx.params.id) //条件查询 const detail=await this.app.model.User.findOne({ where:{ id:this.ctx.request.body.id } }) if(!detail){ return this.ctx.body={ msg='fail' data='用户不存在' } } //查询多个 let Op=this.app.Sequelize.Op //疑似查询选项(以配置的形式写SQL语句??) const detail=await this.app.model.User.findAll({ where:{ id:{[Op.like]:'%'+this.ctx.query.key+'%'} }, attributes:['id','username','sex'], //字段限制 //attributes{exclude:['password']} //字段限制(反限制) order:[['id','DESC']], //顺序限制(可多限制,有优先级) limit:toInt(ctx.query.limit), //数量限制 offset:toInt(ctx.query.offset) //偏移 }) //返回 this.ctx.body={ msg='ok' data=detail } }
修改
async update(){ //主键查询 const data=await this.app.model.User.findByPk(this.ctx.params.id) if (!data){ return this.ctx.body={ msg='fail' data='用户不存在' } } data.username=this.ctx.request.body.username let res=await data.save() //let res=await data.save(field:['title']) //限制字段不允许修改 //await data.update(this.ctx.request.body,{field:['password']}) //等效update调用 //返回 this.ctx.body={ msg='ok' data=res } }
删除
async destroy(){ //主键查询 const id=this.ctx.params.id?parseInt(this.ctx.params.id):0 const data=await this.app.model.User.findByPk(id) if (!data){ return this.ctx.body={ msg='fail' data='用户不存在' } } let res=await data.destroy() this.ctx.body={ msg='ok' data=res } //批量删除 const Op=this.app.model.Sequelize.Op const res= await this.ctx.model.User.destroy({ where:{ id:{ [Op.lte]:7 } } }) this.ctx.body={ msg='ok' data=res } }
错误和异常处理
//app/middleware/error_handle.js module.exports=(option,app)=>{ return async function errorHandle(ctx,next){ try{ await next() }catch(err){ //触发error事件,框架会记录一条错误日志 ctx.app.emit('error',err,ctx) const status=err.status||500 const error=status===500&&ctx.app.config.env==='prod'?'Internal Server Error':err.message ctx.body={error} if(status===422) //参数验证错误?? ctx.body.data=err.errors ctx.status=status } } }
中间件的文件名可以下划线,文件里的方法名需要对应而且必须是驼峰写法
要记得在config/config.default.js里注册中间件
参数验证
安装插件npm install egg-valparams -S
//config/plugin.js valparams:{ enable:true, package:'egg-valparams' } //config/config.default.js config.valparams={ locale:'zh-cn', throwErroe:false } //app/router/user.js async XXX(){ const {ctx}=this ctx.validate({ username:{type:'string',required:true,defValue:'account',desc:'账号'}, password:{type:'string',required:true,defValue:'password',desc:'密码'} }) if(ctx.paramErrors){} const params=ctx.params const{query,body}=ctx.request ctx.body=query }
中间件配置
config.middleware=['errorHandle'] config.errorHandle={ ceshi:123, enable:true, //是否开启中间件 match:'/news', //允许的路径 ignore:'/shop', // 忽略的路径 match(ctx){ //match和ignore都允许多种方式进行配置(函数,字符串,正则,数组) const reg=/iphone|ipad|ipod/i return reg.test(ctx.get('user-agent')) } }
match和ignore不允许同时配置
关闭csrf,开启跨域
安装egg-cors
npm install egg-cors -S
使用插件
//{app_root}/config/plugin.js module.exports={ cors:{ enable:true, package:'egg-cors' } }
配置插件
//cofig/config.default.js module.exports={ cofig.security={ //关闭csrf csrf:{ enable:false }, domainWhiteList:[] } //允许跨域的方法 config.cors={ origin: '*', allowMethods: 'GET,POST,PUT,DELETE,PATCH' } }
OP操作符
const Op=Sequelize.Op [Op.and]:{a:5} //且a=5 [Op.or]:{a:5},{a:6} //a=5或a=6 [Op.gt]:6 //a>6 [Op.gte]:6 //a>=6 [Op.lt]:6 //a<6 [Op.lte]:6 //a<=6 [Op.ne]:20 //a≠5 [Op.eq]:{a:5} //且a=5 [Op.not]:true //非真(not True) [Op.between]:[6,10] //6到10之间 [Op.notBetween]:[11,15] //不11到15之间 [Op.in]:[6,10] //在[6,10]中 [Op.notIn]:[6,10] //不在[6,10]中 [Op.like]:'%hat' //包含%hat [Op.like]:'%hat' //包含%hat [Op.notLike]:'%hat' //不包含%hat [Op.iLike]:'%hat' //包含%hat(不区分大小写)【仅限PG】 [Op.notILike]:'%hat' //不包含%hat(不区分大小写)【仅限PG】 [Op.startWith]:'hat' //类似hat% [Op.endWith]:'hat' //类似%hat [Op.subString]:'hat' //类似%hat% [Op.regexp]:'^[h|a|t]' //正则【仅限MySQL/PG】 [Op.regexp]:'^[h|a|t]' //反正则【仅限MySQL/PG】 [Op.iRegexp]:'^[h|a|t]' //~*'^[h|a|t]'【仅限PG】 [Op.notIRegexp]:'^[h|a|t]' //!~*'^[h|a|t]'【仅限PG】 [Op.like]:{[Op.any]:['cat','hat']} //包含任何数组['cat','hat']同样适用于iLike和notLike [Op.oberlap]:[1, 2] //&&[1,2](PG数组重叠运算符) [Op.contains]:[1, 2] //@>[1,2](PG数组重叠运算符) [Op.contained]:[1, 2] //<@[1,2](PG数组重叠运算符) [Op.any]:[2, 3] //任何[1,2]::INTEGER(PG数组重叠运算符) [Op.col]:'user.organization_id' //='user'.'organization_id'使用数据库语言特定的列标识符
版权归属:
tutu
许可协议:
本文使用《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》协议授权
评论区