# 常用方法
# 模型方法
# 基本方法
// 排序
order() // 多个排序用逗号隔开DESC,ASC
// 分页
page() // 页码,每页条数
// 字段返回限制
field() // 多个字段用逗号隔开
//条件查询
where()
// 传入查询条件,推荐对象方式,可配合find(),select(),countSelect()...,查询符合条件的数据
// 多表查询
join() // 推荐关联查询不超过三张,业务特殊除外
// 单表查询
find() // 限制查询一条符合结果的数据
// 多条查询
select() // 不限制条数查询
// 多条查询
countSelect() // 分页查询,结果包含: 总记录数,当前页,每页多少条
// 别名操作
alias() // 指定别名
// 新增操作
add()
// 修改操作
update()
// 删除操作 使用自定义基类为(逻辑删除)
delete()
// 删除操作 仅支持自定义基类 真实删除)
destory()
# 下面是一些使用案例
1.新增数据
// 新增操作
let result = await this.add({ username: 'admin2', nickname: '超管二号' });
2.修改数据
// 修改操作
let result = await this.where({id: 1 })
.update({ username: 'admin2', nickname: '超管二号' });
3.删除数据
// 删除操作 使用自定义基类为(逻辑删除),使用原生基类则为真实删除,需注意!!
//默认情况下我们使用逻辑删除,删除数据
let result = await this.where({ id: 1}).delete();
// 删除操作 仅支持自定义基类 真实删除)
let results = await this.where({ id: 1}).destory();
4.查询数据
// 1. 单表操作 find() 查询username = "admin" 的数据,并且只返回一条数据,
let result = await this.field('id,username,nickname,password')
.where({username: 'admin'}).find();
// 2. 单表操作 select() 查询username = "admin" 的并返回多条数据,
//不分页,并且根据创建时间倒叙,更新时间倒叙
let result = await this.where({username: 'admin'})
.order('create_at desc,update_at desc').select();
// 3. 单表操作 select() 分页 查询第一页,并且每页十条
let result = await this.page(1, 10).countSelect();
// 4. 多表操作 countSelect() 分页 分页查询一页十条,内连接查询,有多张表在join后继续添加join
let result = await this.join({
join: 'inner',
table: 'entity_branch',
as: 'entity_branch',
on: {
'auth_user.id_entity_branch': 'entity_branch."id"',
'entity_branch.is_rec': false
}
})
.page(1,10)
.alias('auth_user')
.countSelect();
// 5.模糊查询
let where = {
username: ['like', `%你好%`]
}
let result = await this.where(where).order('create_at desc').select();
// 6.in查询 反之改成 id: ['not in',[1,2,3,4]]
let where = {
id: ['in',[1,2,3,4]]
}
let result = await this.where(where).order('create_at desc').select();
// 7.or查询 或查询
let where = {
'username|nickname': 'admin'
}
let result = await this.where(where).order('create_at desc').select();
# 事务处理
在进行多表操作,如同时对多表进行添加时需要使用事务进行数据添加,避免出现错误,错误的添加数据。
# 自动控制
- 优点:使用简单,不容易犯错,就感觉事务不存在的样子。
- 缺点:整个事务要么成功,要么失败,无法做细粒度控制。
module.exports = class extends think.Controller {
async indexAction() {
let models=think.modelPro()
const data = await models.transaction(async () => {
let data1 = await think.modelPro('device').db(models.db()) //复用实例,不可少
.add({id_device_type: '测试添加2'})
let datas = await think.modelPro('entity_branch')
.db(models.db()).add({id_entity: "测试添加"})
return true;
})
return this.success(data);
}
};
# 手动控制
- 优点:startTrans, commit 或 rollback 都由开发者来完全控制,可以做到非常细粒度的控制。
- 缺点:手写代码比较多,不是每个人都能写好。忘记了捕获异常和 cleanup 都会导致严重 bug。
module.exports = class extends think.Controller {
async indexAction() {
let models=think.modelPro() //创建实例
try{
await models.startTrans(); //开启事务
let data = await think.modelPro('device').db(models.db()) //复用实例,不可少
.add({id_device_type: '测试添加2'})
let datas = await think.modelPro('entity_branch')
.db(models.db()).add({id_entity: "测试添加"})
await models.commit(); //提交事务
return this.success(datas);
}catch(e){
await models.rollback() // 一定记得捕获异常后回滚事务!!
}
}
};
以上两种方式都可以进行事务操作,可以根据实际情况选择合适的方式。
注意事项
1.由于操作事务过程需要实例化多个模型操作,那么需要让模型之间复用同一个数据库连接,具体见 model.db (opens new window)
- 事务操作过程要尽量小,因为等待的时候,事务并未结束,可能锁定了很多资源,所以建议处理好数据在执行事务操作。
# 手动Sql
在进行比较复杂的操作,使用模型自带的方法显然难以实现我们想要的功能,这时候我们需要执行原生sql来实现功能,但是这样很容易引起 sql 注入!!, 所以下面主要讲解如何在使用原生sql的时候尽可能的避免风险。
1.下面是一个比较简单的使用场景,在使用原生sql请不要使用字符串拼接的方式将数据拼接到sql语句在。我们应该使用占位符进行拼接, 这样可以很好的避免被注入风险。
const query = `SELECT * FROM zee_account_user WHERE id_auth_role = $(list.name)
and id_entity in ($(password:value))`;
let datas={list:{name:3},password:[1,2,3]}
let data =await think.modelPro().queryPro(query,datas)
//在上面的语句中 $(list.name)表示获取对象在list.name的值,
//$(password:value)则表示获取password并将数组内的值取出来
/**
* 可传入值
* @param {String} sql sql语句
* @param {obj} perch 占位符
*/
2.下面是一个比较常见的使用场景,当我们不确定某个值是不是一定会传入时,则需要拼接sql,下面是一个拼接案例。
let datas={
name:'name'
password:[1,2,3]
}
const query = "SELECT * FROM zee_account_user WHERE 1=1";
if(datas.name){
query+='and id_auth_role like $(name)'
datas.name= `%${datas.name}%`
}
if(datas.password){
query+='and id_entity in ($(password:value))'
}
let data =await think.modelPro().queryPro(query,datas)
/**
* 可传入值
* @param {String} sql sql语句
* @param {obj} perch 占位符
*/
注意事项
1.使用sql语句不能将数据直接拼接到sql中,这是不安全的!!!
2.简单的sql应该使用model自带的方法进行查询,而不是使用直接使用sql。
# 通用方法
# 框架常用方法
# 是否数字,且大于0
// 验证返回是否为数字,且数字大于0,是则为true
think.isCorrect()
# 是否数组
// 判断输入是否是数组,是则为true
think.isArray(arr)
# 否为对象
// 判断是否为对象,是则为true
think.isObject()
# 是否真正为空
// 判断是否是真正为空,undefined、null、''、NaN,是则为true
think.isTrueEmpty(boolean)
# 对象是否为空
// 判断对象是否为空, undefined, null ,'', NaN, [], {}, 0, false,是则为true
think.isEmpty(arr)
# md5加密
// md5加密
think.md5(name)
# 格式化日期
// 格式化日期
think.datetime(date, 'YYYY-MM-DD HH:mm:ss' )
# uuid
// 生成 uuid 字符串 支持v1|v4
think.uuid()
# 数据格式化为二维存库
// 数据格式化为二维存库
think.formattingKeep()
# 自定义方法
# 加密/解密token
//加密token
think.Utils.signteToken(data)
// 解密token,是则为false
think.Utils.verifyToken(token)
# http请求
think.Utils.request()
/**
* 可传入值
* @param {String} url 请求地址
* @param {deploy} deploy 配置参数
*/
/**
* 常用参数 deploy
* @param {string} method 请求类型,默认为post
* @param {obj} data post请求数据
* @param {obj} headers 请求头,默认为 "content-type": "application/json"
* @param {obj} params get请求参数,也可拼接到url
*/
# 用户信息
// 获取用户信息
let user= think.User
//设置用户信息
think.User= await {id:1111}
# 数据缓存
//设置缓存
// 默认时间为2天
think.cache('AccessToken', access_token, { timeout: 1.5 * 60 * 60 * 1000 })
// 获取缓存
think.cache('AccessToken')
//清除缓存
think.cache('AccessToken', mull)
# 导出exel
const columns = [
{
label: '姓名',
value: 'name',
},
{
label: '年龄',
value: 'age',
}
]
const data = [
{
name: 'lucy',
age: 24
},
{
name: 'bob',
age: 26
}
]
const sheetOptions = {'!cols': [{wch: 20}, {wch: 15}, {wch: 15}, {wch: 25}]};// 配置列宽
let result = await think.Utils.JsonToExcel([{name:'测试',columns:columns,data:data}],{sheetOptions})
// 输出流数据
////配置参数返回前端
this.ctx.set({
'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'Content-Disposition': 'attachment; filename=test.xlsx'
});
this.ctx.body = result;
/**
* 可传入值
* @param {String} data 数据列表
* @param {deploy} deploy 配置参数如sheetOptions
*/
/**
* data
* @param {string} name 工作谱名称
* @param {obj} columns 列表头
* @param {obj} data 导出数据
*
*/
///注,如果一个文件想要导出多个工作谱则data配置多个对象即可
← 进阶功能