0% found this document useful (0 votes)
41 views129 pages

Thinkjs ZH-CN 3.0

Uploaded by

gp.liang
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
41 views129 pages

Thinkjs ZH-CN 3.0

Uploaded by

gp.liang
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 129

ThinkJS 3.

0 Documentation

ThinkJS Node.js
3.0 ThinkJS koa 2.x koa middleware

ThinkJS Extend Adapter

Middleware Extend Adapter


Koa 2.x

async/await */yield
ThinkJS ES6
Node.js 6.x LTS

ThinkJS

$ npm install -g think-cli

thinkjs thinkjs -v

2.x
thinkjs new [project_name]

$ thinkjs new demo;


$ cd demo;
$ npm install;
$ npm start;

[2017-06-25 15:21:35.408] [INFO] - Server running at http://127.0.0.1:8360


[2017-06-25 15:21:35.412] [INFO] - ThinkJS version: 3.0.0-beta1
[2017-06-25 15:21:35.413] [INFO] - Enviroment: development
[2017-06-25 15:21:35.413] [INFO] - Workers: 8

http://127.0.0.1:8360/ IP

|--- development.js //开发环境下的⼊入⼝口⽂文件


|--- nginx.conf //nginx 配置⽂文件
|--- package.json
|--- pm2.json //pm2 配置⽂文件
|--- production.js //⽣生成环境⼊入⼝口⽂文件
|--- README.md
|--- src
| |--- bootstrap //启动字执⾏行行⽬目录
| | |--- master.js //Master 进程下⾃自动执⾏行行
| | |--- worker.js //Wokre 进程下⾃自动执⾏行行
| |--- config //配置⽂文件⽬目录
| | |--- adapter.js // adapter 配置
| | |--- config.js // 默认配置⽂文件
| | |--- config.production.js //⽣生产环境下的默认配置⽂文件,和 config.js 合并
| | |--- extend.js //项⽬目扩展配置⽂文件
| | |--- middleware.js //中间件配置⽂文件
| | |--- router.js //⾃自定义路路由配置⽂文件
| |--- controller //控制器器⽬目录
| | |--- base.js
| | |--- index.js
| |--- logic //logic ⽬目录
| | |--- index.js
| |--- model //模型⽬目录
| | |--- index.js
|--- view //模板⽬目录
| |--- index_index.html
|--- www
| |--- static //存放静态资源⽬目录
| | |--- css
| | |--- img
| | |--- js

2.x 3.x

3.0 Koa 2.x Koa

http ctx
middleware

2.x src/bootstrap/ 3.0

Master src/boostrap/master.js
Woker src/boostrap/worker.js

require

2.x src/config/ 3.0

hook middleware

3.x hook middleware Koa middleware middleware


src/config/middleware.js
2.x middleware 3.0 3.0 Koa middleware

Controller

think.controller.base think.Controller think.controller.rest

Model

think.model.base think.Model

ThinkJS

npm start node development.js


ThinkJS Application run
Master Worker
Master

think.config think.logger
src/bootstrap/matser.js
src/
app/
workers fork Worker Worker appReady
think.app.on("appReady")
Worker fork
Worker

think.config think.logger
Extend src/config/extend.js
think.app.modules

controller src/controller/*.js think.app.controllers


logic src/logic/*.js think.app.logics
model src/model/*.js think.app.models
service src/service/*.js think.app.services
src/config/router.js think.app.routers
src/config/validator.js think.app.validators
middleware src/config/middleware.js think.app.use

src/config/crontab.js
src/bootstrap/worker.js
process onUncaughtException onUnhandledRejection
src/config.js
think.beforeStartServer

createServer
createServer(port, host, callback)
think.app.listen
appReady think.app.on("appReady")

think.app.server

[2017-07-02 13:36:40.646] [INFO] - Server running at http://127.0.0.1:8360


[2017-07-02 13:36:40.649] [INFO] - ThinkJS version: 3.0.0-beta1
[2017-07-02 13:36:40.649] [INFO] - Enviroment: development
[2017-07-02 13:36:40.649] [INFO] - Workers: 8

webserver nginx node


node
node Master Worker
Worker middleware

meta ThinkJS

resource www/static/
middleware middleware
trace

payload
request.body
router Controller Action ctx.controller
ctx.action ctx.module
logic controller action logic

logic ctx
__before false
xxxAction false
xxxAction __call
__after false
false
controller controller action controller

logic
404
action this.body
Worker onUncaughtException onUnhandledRejection Worker
Master fork Worker

middleware
middleware

middleware middleware
next

function middlewareFunction(options){
return (ctx, next) => {
if(userLogin){ //这⾥里里判断如果⽤用户登录了了才执⾏行行后续的⾏行行为
return next();
}
}
}

Logic Controller __before __after

false
__before(){
if(!userLogin) return false; //这⾥里里⽤用户未登录时返回了了 false,那么后⾯面的 xxxAction 不不再
执⾏行行
}

ThinkJS
src/config/

config.js
adapter.js adapter
router.js
middleware.js middlware
validator.js
extend.js

// src/config.js

module.exports = {
port: 1234,
redis: {
host: '192.168.1.2',
port: 2456,
password: ''
}
}

[name].[env].js config.development.js
config.production.js
config.js adapter.js

[ThinkJS]/lib/config.js
[ThinkJS]/lib/config.[env].js
[ThinkJS]/lib/adapter.js
[ThinkJS]/lib/adapter.[env].js
src/config/config.js
src/config/config.[env].js
src/config/adapter.js
src/config/adapter.[env].js

[env] key

think-loader https://github.com/thinkjs/think-loader/b
lob/master/loader/config.js

ctx ctx.config(key)
controller controller.config(key)
think.config(key)

ctx.config controller.config think.config

const redis = ctx.config('redis'); //获取 redis 配置

think.config(key, value)

// src/bootstrap/worker.js
//HTTP 服务启动前执⾏行行
think.beforeStartServer(async () => {
const config = await think.model('config').select();
think.config('userConfig', config); //从数据库中将配置读取出来,然后设置
})

不不能

config.js adapter.js key

不不能 config.js adapter.js key

Context

Context Koa request response middleware


controller ctx

ThinkJS Extend
https://github.com/thinkjs/thinkjs/blob/3.0/lib/extend/context.js

API

userAgent

ctx.userAgent userAgent

const userAgent = ctx.userAgent;


if(userAgent.indexOf('spider')){
...
}
isGet

ctx.isGet GET

const isGet = ctx.isGet;


if(isGet){
...
}

isPost

ctx.isPost POST

const isPost = ctx.isPost;


if(isPost){
...
}

isCli

ctx.isCli CLI

const isCli = ctx.isCli;


if(isCli){
...
}

referer(onlyHost)

onlyHost {Boolean} host


return {String}

referer

const referer1 = ctx.referer(); // http://www.thinkjs.org/doc.html


const referer2 = ctx.referer(true); // www.thinkjs.org
referrer(onlyHost)

referer

isMethod(method)

method {String}
return {Boolean}

method

const isPut = ctx.isMethod('PUT');

isAjax(method)

method {String}
return {Boolean}

ajax header x-requested-with XMLHttpRequest


method

const isAjax = ctx.isAjax();


const isPostAjax = ctx.isAjax('POST');

isJsonp(callbackField)

callbackField {String} callback this.config('jsonpCallbackField')


return {Boolean}

jsonp

const isJsonp = ctx.isJson('callback');


if(isJsonp){
ctx.jsonp(data);
}

jsonp(data, callbackField)
data {Mixed}
callbackField {String} callback this.config('jsonpCallbackField')
return {Boolean} false

jsonp false jsonContentType


Content-Type

ctx.jsonp({name: 'test'});

//output
jsonp111({
name: 'test'
})

json(data)

data {Mixed}
return {Boolean} false

json false jsonContentType


Content-Type

ctx.json({name: 'test'});

//output
{
name: 'test'
}

success(data, message)

data {Mixed}
message {String} errmsg
return {Boolean} false

errno errmsg errno 0 errmsg message

{
errno: 0,
errmsg: '',
data: ...
}
errno errmsg errnoField errmsgField

fail(errno, errmsg, data)

errno {Number}
errmsg {String}
data {Mixed}
return {Boolean} false

{
errno: 1000,
errmsg: 'no permission',
data: ''
}

errno errmsg errnoField errmsgField

expires(time)

time {Number} 1s 1m
return {undefined}

Cache-Control Expires

ctx.expires('1h'); //缓存⼀一⼩小时

config(name, value, m)

name {Mixed}
value {Mixed}
m {String}
return {Mixed}

think.config

ctx.config('name'); //获取配置
ctx.config('name', value); //设置配置值
ctx.config('name', undefined, 'admin'); //获取 admin 模块下配置值,多模块项⽬目下⽣生效
param(name, value)

name {String}
value {Mixed}
return {Mixed}

URL get query Koa


param

ctx.param('name'); //获取参数值,如果不不存在则返回 undefined


ctx.param(); //获取所有的参数值,包含动态添加的参数
ctx.param('name1,name2'); //获取指定的多个参数值,中间⽤用逗号隔开
ctx.param('name', value); //重新设置参数值
ctx.param({name: 'value', name2: 'value2'}); //重新设置多个参数值

post(name, value)

name {String}
value {Mixed}
return {Mixed}

POST

ctx.post('name'); //获取 POST 值,如果不不存在则返回 undefined


ctx.post(); //获取所有的 POST 值,包含动态添加的数据
ctx.post('name1,name2'); //获取指定的多个 POST 值,中间⽤用逗号隔开
ctx.post('name', value); //重新设置 POST 值
ctx.post({name: 'value', name2: 'value2'}); //重新设置多个 POST 值

file(name, value)

name {String}
value {Mixed}
return {Mixed}

ctx.file('name'); //获取 FILE 值,如果不不存在则返回 undefined


ctx.file(); //获取所有的 FILE 值,包含动态添加的数据
ctx.file('name', value); //重新设置 FILE 值
ctx.file({name: 'value', name2: 'value2'}); //重新设置多个 FILE 值
{
"size": 287313, //⽂文件⼤大⼩小
"path": "/var/folders/4j/g57qvmmd1lb_9h605w_d38_r0000gn/T/upload_fa6bf8c44179851
f1cfec99544b4ef22", //临时存放的位置
"name": "An Introduction to libuv.pdf", //⽂文件名
"type": "application/pdf", //类型
"mtime": "2017-07-02T07:55:23.763Z" //最后修改时间
}

cookie(name, value, options)

name {String} Cookie


value {mixed} Cookie
options {Object} Cookie
return {Mixed}

Cookie

ctx.cookie('name'); //获取 Cookie


ctx.cookie('name', value); //设置 Cookie
ctx.cookie(name, null); //删除 Cookie

Cookie value 4094 cookieLimit


think.app.on("cookieLimit")

controller(name, m)

name {String} controller


m {String}
return {Object} Class Instance

Controller think.controller

//获取 src/controller/user.js 的实例例


const controller = ctx.controller('user');
service(name, m)

name {String} service


m {String}
return {Mixed}

service service

// 获取 src/service/github.js 模块
const github = ctx.service('github');

Middleware

3.0 Koa@2 Koa@2 middleware

Koa app.use

const app = new Koa();


const bodyparser = require('koa-bodyparser');
app.use(bodyparser({}));

middleware ThinkJS middleware


src/config/middleware.js

const path = require('path')


const isDev = think.env === 'development'

module.exports = [
{
handle: 'meta',
options: {
logRequest: isDev,
sendResponseTime: isDev,
},
},
{
handle: 'resource',
enable: isDev,
options: {
root: path.join(think.ROOT_PATH, 'www'),
publicPath: /^\/(static|favicon\.ico)/,
},
}
]

middleware handle enable options match

handle

middleware
middleware

middleware

module.exports = (options, app) => {


return (ctx, next) => {

}
}

middleware options app Koa Application

enable

middleware middleware

{
handle: 'resouce',
enable: think.env === 'development' //这个 middleware 只在开发环境下⽣生效
}

options

middleware

module.exports = [
{
handle:
}
]

match

middleware

module.exports = [
{
handle: 'xxx-middleware',
match: '/resource' //请求的 URL 是 /resource 打头时才⽣生效这个 middleware
}
]

module.exports = [
{
handle: 'xxx-middleware',
match: ctx => { // match 为⼀一个函数,将 ctx 传递给这个函数,如果返回结果为 true,则启⽤用
该 middleware
return true;
}
}
]

middleware

middleware

module.exports = [
{
handle: 'meta',
options: {}
}
]

meta meta ThinkJS


resource webserver
trace
payload koa-bodyparser middleware
router
logic logic
controller controller action

middleware

middleware src/middleware

src/middleware/csrf.js csrf
middleware

module.exports = [
{
handle: 'csrf',
options: {}
}
]

middleware

middleware require middlware


Koa@2

const csrf = require('csrf');


module.exports = [
...,
{
handle: csrf,
options: {}
},
...
]

middleware

middleaware

middleware
DEBUG=koa:application node development.js
koa:application use ...

worker

Logic

Action

Action Action

ThinkJS Logic Logic Action


Action Action Logic Action

Logic

Logic src/[module]/logic thinkjs controller test


test Controller Logic

Logic

module.exports = class extends think.Logic {


__before() {
// todo
}
indexAction() {
// todo
}
__after() {
// todo
}
}

Logic Controller

Logic Action Controller Action Logic __before


__after

Action
module.exports = class extends think.Logic {
indexAction() {
this.allowMethods = 'post'; // 只允许 POST 请求类型
}
detailAction() {
this.allowMethods = 'get,post'; // 允许 GET、POST 请求类型
}
}

字段名 : JSON 配置对象

module.exports = class extends think.Logic {


indexAction(){
let rules = {
username: {
string: true, // 字段类型为 String 类型
required: true, // 字段必填
default: 'thinkjs', // 字段默认值为 'thinkjs'
trim: true, // 字段需要trim处理理
method: 'GET' // 指定获取数据的⽅方式
},
age: {
int: {min: 20, max: 60} // 20到60之间的整数
}
}
let flag = this.validate(rules);
}
}

boolean string int float array object


string

header

module.exports = class extends think.Logic {


saveAction(){
let rules = {
username: {
value: this.header('x-name') // 从 header 中获取值
}
}
}
}

version
GET this.param('version') version
POST this.post('version') FILE
this.file('version') verison

POST URL
GET POST FILE

default:value

trim:true trim trim

this.validate

module.exports = class extends think.Logic {


indexAction(){
let rules = {
username: {
required: true
}
}
let flag = this.validate(rules);
if(!flag){
return this.fail('validate error', this.validateErrors);
// 如果出错,返回
// {"errno":1000,"errmsg":"validate error","data":{"username":"username can
not be blank"}}
}
}
}

controller action this.isGet this.isPost


this.isGet this.isPost

module.exports = class extends think.Logic {


indexAction(){
if(this.isPost) {
let rules = {
username: {
required: true
}
}
let flag = this.validate(rules);
if(!flag){
return this.fail('validate error', this.errors());
}
}

}
}

false this.validateErrors
this.fail JSON
this.display Logic Controller Controller

JSON
this.validate this.rules

module.exports = class extends think.Logic {


indexAction(){
this.rules = {
username: {
required: true
}
}
}
}
module.exports = class extends think.Logic {
indexAction(){
let rules = {
username: {
required: true
}
}
let flag = this.validate(rules);
if(!flag){
return this.fail(this.config('validateDefaultErrno') , this.validateErrors);
}
}
}

this.rules Action
JSON

children

module.exports = class extends think.Logic {


let rules = {
username: {
array: true,
children: {
string: true,
trim: true,
default: 'thinkjs'
},
method: 'GET'
}
}
this.validate(rules);
}

children

module.exports = class extends think.Logic {


let rules = {
username: {
object: true,
children: {
string: true,
trim: true,
default: 'thinkjs'
},
method: 'GET'
}
}
this.validate(rules);
}

boolean 'yes' 'on' '1' 'true' true true


false

array
split(',') [字段值]

int float numeric


parseFloat

module.exports = class extends think.Logic {


indexAction(){
let rules = {
age: {
int: true,
method: 'GET'
}
}
let flag = this.validate(rules);
}
}

url age=26 Logic typeof this.param('age') number


config valadator.js
common/config valadator.js valadator.js

, GET name1 lucy ;


/index/?name1=jack

// logic index.js
module.exports = class extends think.Logic {
indexAction() {
let rules = {
name1: {
eqValid: 'lucy',
method: 'GET'
}
}
let flag = this.validate(rules);
if(!flag) {
console.log(this.validateErrors); // name1 shoud eq lucy
}
}
}
}

// src/config/validator.js
module.exports = {
rules: {
/**
* @param {Mixed} value [相应字段的请求值]
* @param {Mixed} parsedValue [校验规则的参数值]
* @param {String} validName [校验规则的参数名称]
* @return {Boolean} [校验结果]
*/
eqValid(value, parsedValue, validName) {
console.log(value, parsedValue, validName); // 'jack', 'lucy', 'eqValid'
return value === parsedValue;
}
},
messages: {
eqValid: '{name} should eq {args}'
}
}
GET name1 name2
/index/?name1=tom&name2=lily

// logic index.js
module.exports = class extends think.Logic {
indexAction() {
let rules = {
name1: {
eqValid: 'name2',
method: 'GET'
}
}
let flag = this.validate(rules);
if(!flag) {
console.log(validateErrors); // name1 shoud eq name2
}
}
}

// src/config/validator.js
module.exports = {
rules: {
/**
* 需要下划线开头的同名⽅方法
* @param {Mixed} validValue [校验规则的参数值]
* @param {Mixed} query [校验规则method指定的参数来源下的参数]
* @param {String} validName [校验规则的参数名称]
* @return {Mixed} [解析之后的校验规则的参数值]
*/
_eqValid(validValue, query, validName){
console.log(validValue, query, validName); // 'name2', {name1: 'tom', name2:
'lily'}, 'eqValid'
let parsedValue = query[validValue];
return parsedValue;
},

/**
* @param {Mixed} value [相应字段的请求值]
* @param {Mixed} parsedValue [_eqValid⽅方法返回的解析之后的校验规则的参数值]
* @param {String} validName [校验规则的参数名称]
* @return {Boolean} [校验结果]
*/
eqValid(value, parsedValue, validName) {
console.log(value, parsedValue, validName); // 'tom', 'lily', 'eqValid'
return value === parsedValue;
}
},
messages: {
eqValid: '{name} should eq {args}'
}
}
{name} {args} {pargs} {name}
{args} {pargs}
{args} {pargs} JSON.stringify

Object: true 1
2 3 { }

3> 2> 1

module.exports = class extends think.Logic {


let rules = {
username: {
required: true,
method: 'GET'
}
}
let msgs = {
required: '{name} can not blank', // 规则 1
username: '{name} can not blank', // 规则 2
username: {
required: '{name} can not blank' // 规则 3
}
}
this.validate(rules, msgs);
}

Object: true 5 > (4 = 3) > 2 > 1

module.exports = class extends think.Logic {


let rules = {
address: {
object: true,
children: {
int: true
}
}
}
let msgs = {
int: 'this is int error message for all field', // 规则1
address: {
int: 'this is int error message for address', // 规则2
a: 'this is int error message for a of address', // 规则3
'b,c': 'this is int error message for b and c of address' // 规则4
d: {
int: 'this is int error message for d of address' // 规则5
}
}
}
let flag = this.validate(rules, msgs);
}

required

required: true required: false undefined 空字符串串 null NaN


required: true

module.exports = class extends think.Logic {


indexAction(){
let rules = {
name: {
required: true
}
}
this.validate(rules);
// todo
}
}

name

requiredIf

module.exports = class extends think.Logic {


indexAction(){
let rules = {
name: {
requiredIf: ['username', 'lucy', 'tom'],
method: 'GET'
}
}
this.validate(rules);
// todo
}
}
GET username lucy tom name

requiredNotIf

module.exports = class extends think.Logic {


indexAction(){
let rules = {
name: {
requiredNotIf: ['username', 'lucy', 'tom'],
method: 'POST'
}
}
this.validate(rules);
// todo
}
}

POST username lucy tom name

requiredWith

module.exports = class extends think.Logic {


indexAction(){
let rules = {
name: {
requiredWith: ['id', 'email'],
method: 'GET'
}
}
this.validate(rules);
// todo
}
}

GET id email name


requiredWithAll

module.exports = class extends think.Logic {


indexAction(){
let rules = {
name: {
requiredWithAll: ['id', 'email'],
method: 'GET'
}
}
this.validate(rules);
// todo
}
}

GET id email name

requiredWithOut

module.exports = class extends think.Logic {


indexAction(){
let rules = {
name: {
requiredWithOut: ['id', 'email'],
method: 'GET'
}
}
this.validate(rules);
// todo
}
}

GET id email name

requiredWithOutAll

module.exports = class extends think.Logic {


indexAction(){
let rules = {
name: {
requiredWithOutAll: ['id', 'email'],
method: 'GET'
}
}
this.validate(rules);
// todo
}
}

GET id email name

contains

module.exports = class extends think.Logic {


indexAction(){
let rules = {
name: {
contains: 'ID-',
method: 'GET'
}
}
this.validate(rules);
// todo
}
}

GET name ID-

equals

module.exports = class extends think.Logic {


indexAction(){
let rules = {
name: {
equals: 'username',
method: 'GET'
}
}
this.validate(rules);
// todo
}
}

GET name username

different

module.exports = class extends think.Logic {


indexAction(){
let rules = {
name: {
equals: 'username',
method: 'GET'
}
}
this.validate(rules);
// todo
}
}

GET name username

before

module.exports = class extends think.Logic {


indexAction(){
let rules = {
time: {
before: '2099-12-12 12:00:00', // before: true 早于当前时间
method: 'GET'
}
}
this.validate(rules);
// todo
}
}

GET time 2099-12-12 12:00:00


after

after: true | time string

alpha

[a-zA-Z] alpha: true

alphaDash

[a-zA-Z_] alphaDash: true

alphaNumeric

[a-zA-Z0-9] alphaNumeric: true

alphaNumericDash

[a-zA-Z0-9_] alphaNumericDash: true

ascii

ascii ascii: true

base64

base64 base64: true

byteLength

byteLength: options

module.exports = class extends think.Logic {


indexAction(){
let rules = {
field_name: {
byteLength: {min: 2, max: 4} // 字节⻓长度需要在 2 - 4 之间
// byteLength: {min: 2} // 字节最⼩小⻓长度需要为 2
// byteLength: {max: 4} // 字节最⼤大⻓长度需要为 4
}
}
}
}
creditCard

creditCard: true

currency

currency: true | options options


https://github.com/chriso/validator.js

date

date: true

decimal

0.1 .3 1.1 1.00003 4.0 decimal: true

divisibleBy

divisibleBy: number

module.exports = class extends think.Logic {


indexAction(){
let rules = {
field_name: {
divisibleBy: 2 //可以被 2 整除
}
}
}
}

email

email email: true | options options


https://github.com/chriso/validator.js

fqdn
fqdn: true | options options
https://github.com/chriso/validator.js

float

float: true | options options


https://github.com/chriso/validator.js

module.exports = class extends think.Logic {


indexAction(){
let rules = {
money: {
float: true, //需要是个浮点数
// float: {min: 1.0, max: 9.55} // 需要是个浮点数,且最⼩小值为 1.0,最⼤大值为 9.55
}
}
this.validate();
// todo
}
}

fullWidth

fullWidth: true

halfWidth

halfWidth: true

hexColor

hexColor: true

hex

hex: true

ip

ip ip: true
ip4

ip4 ip4: true

ip6

ip6 ip6: true

isbn

isbn: true

isin

isin: true

iso8601

iso8601 iso8601: true

issn

issn: true

uuid

UUID 3 4 5 ) uuid: true

dataURI

dataURI dataURI: true

md5

md5 md5: true

macAddress

mac macAddress: true


variableWidth

variableWidth: true

in

in: [...]

module.exports = class extends think.Logic {


indexAction(){
let rules = {
version: {
in: ['2.0', '3.0'] //需要是 2.0,3.0 其中⼀一个
}
}
this.validate();
// todo
}
}

notIn

notIn: [...]

int

int int: true | options options


https://github.com/chriso/validator.js

module.exports = class extends think.Logic {


indexAction(){
let rules = {
field_name: {
int: true, //需要是 int 型
//int: {min: 10, max: 100} //需要在 10 - 100 之间
}
}
this.validate();
// todo
}
}
length

length: options

module.exports = class extends think.Logic {


indexAction(){
let rules = {
field_name: {
length: {min: 10}, //⻓长度不不能⼩小于10
// length: {max: 20}, //⻓长度不不能⼤大于10
// length: {min: 10, max: 20} //⻓长度需要在 10 - 20 之间
}
}
this.validate();
// todo
}
}

lowercase

lowercase: true

uppercase

uppercase: true

mobile

mobile: true | options options


https://github.com/chriso/validator.js

module.exports = class extends think.Logic {


indexAction(){
let rules = {
mobile: {
mobile: 'zh-CN' //必须为中国的⼿手机号
}
}
this.validate();
// todo
}
}
mongoId

MongoDB ObjectID mongoId: true

multibyte

multibyte: true

url

url url: true|options options https://github.com/chriso/validator.js

order

order name DESC order: true

field

name,title field: true

image

image: true

startWith

startWith: string

endWith

, endWith: string

string

string: true

array

array: true array


split(,) [字段值]
boolean

'yes' 'on' '1' 'true' true true

object

object: true

regexp

module.exports = class extends think.Logic {


indexAction(){
this.rules = {
name: {
regexp: /thinkjs/g
}
}
this.validate();
// todo
}
}

Controller

user.js Action

Controller

controller think.Controller
controller

base.js controller

//src/controller/user.js

const Base = require('./base.js');


module.exports = class extends Base {
indexAction(){
this.body = 'hello word!';
}
}

http://127.0.0.1:8360/user/index
hello word!

__before

__before

__before Action

module.exports = class extends think.Controller {


async __before(){
const userInfo = await this.session('userInfo');
//获取⽤用户的 session 信息,如果为空,返回 false 阻⽌止后续的⾏行行为继续执⾏行行
if(think.isEmpty(userInfo)){
return false;
}
}
indexAction(){
// __before 调⽤用完成后才会调⽤用 indexAction
}
}

__after

__after __before Action Action


false __after

module.exports = class extends think.Controller {


indexAction(){

}
__after(){
//indexAction 执⾏行行完成后执⾏行行,如果 indexAction 返回了了 false 则不不再执⾏行行
}
}

ctx
controller ctx controller this.ctx ctx
controller ctx

src/controller/ user/ admin/


user/ admin/

API

controller.ctx

ctx

controller.body

return {String}

module.exports = class extends think.Controller {


indexAction(){
this.body = 'hello world';
}
}

controller.ip

return {String}

ip ctx.ip

controller.ips
return {Array}

ip ctx.ips

controller.method

return {String}

controller.isGet

return {Boolean}

GET

controller.isPost

return {Boolean}

POST

controller.isCli

return {Boolean}

controller.userAgent

userAgent

controller.isMethod(method)

method {String}
return {Boolean}

controller.isAjax(method)
method {String}
return {Boolean}

Ajax method

module.exports = class extends think.Controller {


indexAction(){
//是ajax 且请求类型是 POST
let isAjax = this.isAjax('post');
}
}

controller.isJsonp(callback)

callback {String} callback


return {Boolean}

jsonp

controller.get(name)

name {String}

GET

module.exports = class extends think.Controller {


indexAction(){
//获取⼀一个参数值
let value = this.get('xxx');
//获取所有的参数值
let values = this.get();
}
}

controller.post(name)

name {String}

POST

module.exports = class extends think.Controller {


indexAction(){
//获取⼀一个参数值
let value = this.post('xxx');
//获取所有的 POST 参数值
let values = this.post();
}
}

controller.param(name)

name {String}

POST GET

controller.file(name)

name {String}

{
fieldName: 'file', //表单字段名称
originalFilename: filename, //原始的⽂文件名
path: filepath, //⽂文件保存的临时路路径,使⽤用时需要将其移动到项⽬目⾥里里的⽬目录,否则请求结束时会被删

size: 1000 //⽂文件⼤大⼩小
}

{} ctx.file

controller.header(name, value)

name {String} header


value {String} header

header

module.exports = class extends think.Controller {


indexAction(){
let accept = this.header('accept'); //获取 header
this.header('X-NAME', 'thinks'); //设置 header
}
}
controller.expires(time)

time {Number}

Cache-Control Expires

module.exports = class extends think.Controller {


indexAction(){
this.expires(86400); //设置过期时间为 1 天。
}
}

ctx.expires

controller.referer(onlyHost)

referrer {Boolean} host

referrer

controller.referrer(onlyHost)

controller.referer

controller.cookie(name, value, options)

name {String} cookie


value {String} cookie
options {Object}

cookie

module.exports = class extends think.Controller {


indexAction(){
//获取 cookie 值
let value = this.cookie('think_name');
}
}

module.exports = class extends think.Controller {


indexAction(){
//设置 cookie 值
this.cookie('think_name', value, {
timeout: 3600 * 24 * 7 //有效期为⼀一周
});
}
}

module.exports = class extends think.Controller {


indexAction(){
//删除 cookie
this.cookie('think_name', null);
}
}

controller.redirect(url)

url {String} url

controller.jsonp(data, callback)

data {Mixed}
callback {String} callback

jsonp callback

module.exports = class extends think.Controller {


indexAction(){
this.jsonp({name: 'thinkjs'}, 'callback_fn_name');
//writes
'callback_fn_name({name: "thinkjs"})'
}
}

controller.json(data)

data {Mixed}

json

controller.status(status)
status {Number} 404

controller.success(data, message)

ctx.success

controller.fail(errno, errmsg, data)

ctx.fail

View

View 3.0 View


Extend Adapter

Extend View

src/config/extend.js

const view = require('think-view');


module.exports = [
view
]

view

View Adapter

src/config/adapter.js

const nunjucks = require('think-view-nunjucks');


const path = require('path');

exports.view = {
type: 'nunjucks',
common: {
viewPath: path.join(think.ROOT_PATH, 'view'), //模板⽂文件的根⽬目录
sep: '_', //Controller 与 Action 之间的连接符
extname: '.html' //⽂文件扩展名
},
nunjucks: {
handle: nunjucks
}
}

nunjucks

Extend Adapter Controller

module.exports = class extends think.Controller {


indexAction(){
this.assign('title', 'thinkjs'); //给模板赋值
return this.display(); //渲染模板
}
}

assign

this.assign('title', 'thinkjs'); //单条赋值


this.assign({title: 'thinkjs', name: 'test'}); //单条赋值
this.assign('title'); //获取之前赋过的值,如果不不存在则为 undefined
this.assign(); //获取所有赋的值

render

const content1 = await this.render(); //根据当前请求解析的 controller 和 action ⾃自动匹


配模板⽂文件
const content2 = await this.render('doc'); //指定⽂文件名

const content3 = await this.render('doc', 'ejs'); //切换模板类型


const content4 = await this.render('doc', {type: 'ejs', xxx: 'yyy'});//切换模板类型
,并配置额外的参数
display

return this.display(); //根据当前请求解析的 controller 和 action ⾃自动匹配模板⽂文件

return this.display('doc'); //指定⽂文件名

return this.display('doc', 'ejs'); //切换模板类型


return this.display('doc', {type: 'ejs', xxx: 'yyy'});//切换模板类型,并配置额外的参数

Adapter

View Adapter https://github.com/thinkjs/think-awesome#view

URL module controller


action ThinkJS
URL ThinkJS middleware

src/config/middleware.js

const router = require('think-router');


module.exports = [
{
handle: router,
options: {
prefix: 'home', // 多模块下,默认的模块名
defaultController: 'index', // 默认的控制器器名
defaultAction: 'index', // 默认的操作名
prefix: [], // 默认去除的 url 前缀
suffix: ['.html'], // 默认去除的 url 后缀
enableDefaultRouter: true, // 在不不匹配情况下是否使⽤用默认路路由
subdomainOffset: 2, // ⼦子域名偏移
subdomain: {}, // ⼦子域名映射
denyModules: [] // 多模块下,禁⽌止访问的模块
}
}
];
pathname

URL URL
http://www.thinkjs.org/zh-cn/doc/3.0/router.html pathname
/zh-cn/doc/3.0/router.html

URL
URL .html

ThinkJS pathname

{
prefix: [],
suffix: ['.html'],
// 其他配置...
}

prefix subffix
pathname pathname
/zh-cn/doc/3.0/router

URL http://www.thinkjs.org/ pathname /

src/config/router.js

module.exports = [
[/libs\/(.*)/i, '/libs/:1', 'get'],
[/fonts\/(.*)/i, '/fonts/:1', 'get,post'],
];

[
match, // url 匹配规则, 预先使⽤用 path-to-regexp 转换
path, // 对应的操作(action)的路路径
method, // 允许匹配的请求类型,多个请求类型之间逗号分隔,get|post|redirect|rest|cli
[options] // 额外参数,如 method=redirect时,指定跳转码 {statusCode: 301}
]

match path-to-regexp

module.exports = [
['/api_libs/(.*)/:id', '/libs/:1/', 'get'],
]

match :c (c ) match pathname c c


this.ctx path match pathname path :n (n
) match pathname n

[模块]/控制器器/操作/... pathname
(action)

URL http:/www.thinkjs.org/api_libs/inbox/123
path /libs/inbox/ , {id: '123'} this.ctx pathname
libs controller inbox action inboxAction
this.ctx.param('id') id 123

ThinkJS

{
subdomainOffset: 2,
prefix: [],
suffix: ['.html'],
subdomain: {
'news,zm': 'news'
},
// 其他配置...
}

(subdomainOffset) 2 zm.news.so.com this.ctx.subdomains


['news', 'zm'] , 3 this.ctx.subdomains ['zm']
subdomain this.ctx.subdomains.join(,) key key
pathname

http://zm.news.so.com:8360/api_lib/inbox/123
pathname /news/api_lib/inbox/123

subdomain
subdomain: ['admin', 'user'] subdomain: {admin: 'admin', user: 'user'}

Adapter

Adapter

Adapter View Model Cache Session Websocket

Adapter

Adapter src/config/adapter.js

const nunjucks = require('think-view-nunjucks');


const ejs = require('think-view-ejs');
const path = require('path');

exports.view = {
type: 'nunjucks', // 默认的模板引擎为 nunjucks
common: { //通⽤用配置
viewPath: path.join(think.ROOT_PATH, 'view'),
sep: '_',
extname: '.html'
},
nunjucks: { // nunjucks 的具体配置
handle: nunjucks
},
ejs: { // ejs 的具体配置
handle: ejs,
viewPath: path.join(think.ROOT_PATH, 'view/ejs/'),
}
}

exports.cache = {
...
}

type Adapter
common adapter
nunjucks,ejs Adapter common

handle

Adapter

Adapter Adapter

Adapter src/adapter/ src/adapter/cache/xcache.js


xcache cache Adapter cache

Adapter

exports.cache = {
type: 'file',
xcache: {
handle: 'xcache', //这⾥里里配置字符串串,项⽬目启动时会⾃自动查找 src/adapter/cache/xcache.js
⽂文件
...
}
}

Adapter

Adapter https://github.com/thinkjs/think-awesome#adapters

Extend

3.0
Extend think application context
request response controller logic

Extend Session Cache

Extend

Extend src/config/extend.js

const view = require('think-view');


const fetch = require('think-fetch');
const model = require('think-model');

module.exports = [
view, //make application support view
fetch, // HTTP request client
model(think.app)
];

view Extend Controller assign display

Extend

Extend
src/extend/

src/extend/think.js think think.xxx


src/extend/application.js think.app Koa application
src/extend/request.js Koa request
src/extend/response.js Koa response
src/extend/context.js ctx
src/extend/controller.js controller
src/extend/logic.js logic logic controller logic controller

ctx isMobile

//src/extend/context.js
module.exports = {
isMobile: function(){
const userAgent = this.userAgent.toLowerCase();
const mList = ['iphone', 'android'];
return mList.some(item => userAgent.indexOf(item) > -1);
}
}

ctx.isMobile()
getter

//src/extend/context.js
module.exports = {
get isMobile: function(){
const userAgent = this.userAgent.toLowerCase();
const mList = ['iphone', 'android'];
return mList.some(item => userAgent.indexOf(item) > -1);
}
}

ctx this.isMobile ctx.isMobile


controller this.ctx.isMobile

controller this.isMobile controller


isMobile

//src/extend/controller.js
module.exports = {
get isMobile: function(){
return this.ctx.isMobile;
}
}

controller isMobile controller this.isMobile

npm

const controllerExtend = require('./controller.js');


const contextExtend = require('./context.js');

// 模块⼊入⼝口⽂文件
module.exports = {
controller: controllerExtend,
context: contextExtend
}

Extend app

Extend app app

// src/config/extend.js
const model = require('think-model');
module.exports = [
model(think.app) //将 think.app 传递给 model 扩展
];

app

Extend

Extend https://github.com/thinkjs/think-awesome#extends
Extend Pull Request

think

think

think.app

think.app Koa Application

app

think.app.think think app think

think.app.modules
think.app.controllers controller
think.app.logics logic
think.app.models
think.app.services service
think.app.routers
think.app.validators

appReady

think.app.on('appReady', () => {
console.log(think.app.controllers)
})
API

think think-helper think.xxx

think.env

think.app.env development.js

think.isCli

think.version

ThinkJS

think.Controller

think.Logic

logic

think.controller(name, ctx, m)

name {String}
ctx {Object} Koa ctx
m {String}

think.beforeStartServer(fn)

fn {Function}

fn Promise
npm start node production.js

bootstrap

src/boostrap/

Master src/bootstrap/master.js
Worker src/bootstrap/worker.js

Master Worker
master.js worker.js required

// src/bootstrap/common.js
global.commonFn = function(){

// src/bootstrap/master.js
require('./common.js')

// src/boostrap/worker.js
require('./common.js')

node http

think.beforeStartServer

think.beforeStartServer(async () => {
const data = await getDataFromApi();
think.config(key, data);
})
think.beforeStartServer
Promise

startServerTimeout 3

//src/config/config.js
module.exports = {
startServerTimeout: 5000 // 将超时时间改为 5s
}

http

Koa listen http https


createServer

//src/config/config.js
const https = require('https');
const fs = require('fs');

const options = {
key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),
cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem')
};

module.exports = {
// app 为 Koa app 对象
createServer: function(app, ...args){
https.createServer(options, app.callback()).listen(...args);
}
}

think.app.server

http server think.app.server

appReady

http appReady think.app.on("appReady")


think.app.on("appReady", () => {
const server = think.app.server;
})

Service

Cookie

src/config/config.js cookie

module.exports = {
cookie: {
domain: '',
path: '/',
httponly: false, // 是否 http only
secure: false,
timeout: 0 // 有效时间,0 表示载浏览器器进程内有效,单位为秒。
}
}

cookie

controller logic this.cookie cookie

module.exports = class extends think.Controller {


indexAction(){
let cookie = this.cookie('theme'); // 获取名为 theme 的 cookie
}
}

this.ctx cookie cookie

this.ctx.cookie('theme');
cookie

controller logic this.cookie cookie

module.exports = class extends think.Controller {


indexAction(){
let cookie = this.cookie('theme', 'default'); // 将 cookie theme 值设置为 defau
lt
}
}

this.ctx cookie cookie

this.ctx.cookie('theme', 'default');

cookie

module.exports = class extends think.Controller {


indexAction(){
let cookie = this.cookie('theme', 'default', {
timeout: 7 * 24 * 3600 // 设置 cookie 有效期为 7 天
}); // 将 cookie theme 值设置为 default
}
}

cookie

controller logic this.cookie

module.exports = class extends think.Controller {


indexAction(){
let cookie = this.cookie('theme', null); // 删除名为 theme 的 cookie
}
}

this.ctx cookie cookie

this.ctx.cookie('theme', null);
Session

Thinkjs Session controller context session


session cookie mysql file redis

Session

cookie Cookie
mysql Mysql
file
redis Redis

Mysql session

mysql Session SQL

DROP TABLE IF EXISTS `think_session`;


CREATE TABLE `think_session` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`cookie` varchar(255) NOT NULL DEFAULT '',
`data` text,
`expire` bigint(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `cookie` (`cookie`),
KEY `expire` (`expire`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

redis Session

redis Session think-redis

Session

src/config/adapter.js Cookie Session

const cookieSession = require('think-session-cookie');


const fileSession = require('think-session-file');

exports.session = {
type: 'cookie',
common: {
cookie: {
name: 'test',
keys: ['werwer', 'werwer'],
signed: true
}
},
cookie: {
handle: cookieSession,
cookie: {
maxAge: 1009990 * 1000,
keys: ['welefen', 'suredy'],
encrypt: true
}
},
file: {
handle: fileSession,
sessionPath: path.join(think.ROOT_PATH, 'runtime/session')
}
}

* type Session “ session ”


* common Adapter
* cookie,file,mysql Adapter common
handle
* handle

Cookie handle
* maxAge session cookie
* keys encrypt true keys
* encrypt true session

file
* sessionPath session session
'/path_of_your_project/runtime/session'

session

Session
this.session() session
this.session(name) name session

Session

this.session(name, value) session

Session

this.session(null) session

this.session(name, undefined, options) options session

options adapter ctx


this.session options

ctx session

Logger

ThinkJS think-logger3
log4js

logger think.logger debug , info , warn , error

think.logger.debug('debug message');
think.logger.info('info message');
think.logger.warn('warning');
think.logger.error(new Error('error'));
Console , File , DateFile Console

src/config/adapter/logger.js
```javascript
const path = require('path');
const {File} = require('think-logger3');

module.exports = {
type: 'file',
file: {
handle: File,
backups: 10,
absolute: true,
maxLogSize: 50 * 1024, //50M
filename: path.join(think.ROOT_PATH, 'logs/xx.log')
}
}

src/config/adater.js
exports.logger = require('./adapter/logger.js')

logs/xx.log maxLogSize
logs/xx.log.1 backups

filename
maxLogSize KB
backups 5
absolute filename filename absolute
true
layouts
src/config/adapter/logger.js
```javascript
const path = require('path');
const {DateFile} = require('think-logger3');

module.exports = {
type: 'dateFile',
dateFile: {
handle: DateFile,
level: 'ALL',
absolute: true,
pattern: '-yyyy-MM-dd',
alwaysIncludePattern: false,
filename: path.join(think.ROOT_PATH, 'logs/xx.log')
}
}

src/config/adater.js
exports.logger = require('./adapter/logger.js')

logs/xx.log xx.log-2017-07-01
logs/xx.log

level
filename
absolute filename filename absolute
true
pattern

yyyy - yy
MM -
dd - 2
hh - 24
mm -
ss -
SSS -
O -
alwaysIncludePattern alwaysIncludePattern true
xx.log-2017-07-01 xx.log-2017-07-02
layouts

Level

ALL
ERROR
WARN
INFO
DEBUG

Layout

Console , File DateFile layout

const path = require('path');


const {File} = require('think-logger3');

module.exports = {
type: 'file',
file: {
handle: File,
backups: 10,
absolute: true,
maxLogSize: 50 * 1024, //50M
filename: path.join(think.ROOT_PATH, 'logs/xx.log'),
layouts: {
type: 'coloured',
pattern: '%[[%d] [%p]%] - %m',
}
}
}

layouts

type

basic
coloured
messagePassThrough
dummy
pattern
Adding your own layouts
pattern

%r - .toLocaleTimeString() 下午5:13:04
%p -
%h -
%m -
%d - ISO8601 ISO8601 , ISO8601_WITH_TZ_OFFSET ,
ABSOUTE , DATE %d{DATE}
%d{yyyy/MM/dd-hh.mm.ss}
%% - %
%n -
%z - process.pid ID
%[ -
%] -

handle

handle
handle

module.exports = class {
/**
* @param {Object} config {} 配置传⼊入的参数
* @param {Boolean} clusterMode true 是否是多进程模式
*/
constructor(config, clusterMode) {

debug() {

info() {

warn() {

error() {

}
}
node cluster
think-cluster

workers 0 cpu

//src/config/config.js
module.exports = {
workers: 0 // 可以根据实际情况修改,0 为 cpu 的个数
}

Master workers fork Worker Woker


Worker Master Fork Worker
Worker

Worker Worker
Master

think.messenger

think.messenger.broadcast Worker

//监听事件
think.messenger.on('test', data => {
//所有进程都会捕获到该事件,包含当前的进程
});

if(xxx){
//发送⼴广播事件
think.messenger.broadcast('test', data)
}
Master
src/bootstrap/master.js Worker src/bootstrap/worker.js

// src/bootstrap/master.js
process.on('message', (worker, message) => {
// 接收到特定的消息进程处理理
if(message && message.act === 'xxx'){

}
})

// src/bootstrap/worker.js
process.send({act: 'xxxx', ...args}); //发送数据到 Master 进程

Babel

Node 6.0.0 async/await


async/await babel

Babel src/ app/ sourceMap

Babel

Babel Node 7.6.0 8.x.x LTS


-w Babel

thinkjs new demo -w;

Babel

Babel development.js

const Application = require('thinkjs');


const babel = require('think-babel');
const watcher = require('think-watcher');
const notifier = require('node-notifier');
const instance = new Application({
ROOT_PATH: __dirname,
watcher: watcher,
transpiler: [babel, { //转译器器,这⾥里里使⽤用的是 babel,并指定转译参数
presets: ['think-node']
}],
notifier: notifier.notify.bind(notifier), //通知器器,当转译报错时如何通知
env: 'development'
});

instance.run();

Babel development.js

const Application = require('thinkjs');


const watcher = require('think-watcher');
const instance = new Application({
ROOT_PATH: __dirname,
watcher: watcher,
env: 'development'
});

instance.run();

Babel transpiler notifier 2

-w Babel development.js

RESTful API

API API REST API REST


API HTTP

GET /ticket ticket


GET /ticket/:id ticket
POST /ticket ticket
PUT /ticket/:id ticket 12
DELETE /ticket/:id ticekt 12

REST Controller

-r REST Controller
thinkjs controller user -r

create : src/controller/rest.js
create : src/controller/user.js
create : src/logic/user.js

src/controller/user.js src/controller/rest.js rest.js REST


Controller

REST Controller
src/config/router.js

module.exports = [
[/\/user(?:\/(\d+))?/, 'user?id=:1', 'rest']
]

/\/user(?:\/(\d+))?/ URL
user?id=:1 :1 (\d+)
rest REST API

/user/:id REST Controller

GET /user getAction


GET /user/:id getAction
POST /user postAction
PUT /user/:id putAction
DELETE /user/:id deleteAction

Controller Logic
src/logic/user.js Action Controller
Logic
REST API

REST API

module.exports = [
[/\/post\/(\d+)\/comments(?:\/(\d+))?/, 'comment?postId=:1&id=:2', 'rest']
]

Action this.get("postId") id

REST API

REST API

module.exports = [
[/\/v1\/user(?:\/(\d+))?/, 'v1/user?id=:1', 'rest'], //v1 版本
[/\/v2\/user(?:\/(\d+))?/, 'v2/user?id=:1', 'rest'] //v2 版本
]

src/controller/ v1/ v2/

Mongo REST API

Mongo id Mongo REST API


\d \w

module.exports = [
[/\/user(?:\/(\w+))?/, 'user?id=:1', 'rest']
]
MySQL

thinkjs model [name]

thinkjs model user;

src/model/user.js

model.pk

key id

model.schema

{
id: {
name: 'id',
type: 'int', //类型
required: true, //是否必填
primary: true, //是否是主键
unique: true, //是否唯⼀一
auto_increment: true //是否⾃自增
}
}

const moment = require('moment');


module.exports = class extends think.Model {
/**
* 数据表字段定义
* @type {Object}
*/
schema = {
view_nums: { //阅读数
default: 0 //默认为 0
},
fullname: { //全名
default() {
//first_name 和 last_name 的组合,这⾥里里不不能⽤用 Arrows Function
return this.first_name + this.last_name;
}
},
create_time: { //创建时间
default: () => { //获取当前时间
return moment().format('YYYY-MM-DD HH:mm:ss')
},
readonly: true //只读,添加后不不可修改
}
}
}

default
update: true

readonly

注 readonly update

Model -> API

model

module.exports = class extends think.Controller {


indexAction(){
let model = this.model('user');
}
}

think.model
let getModelInstance = function(){
let model = think.model('user', think.config('model'));
}

think.model

jQuery
this

module.exports = class extends think.Model {


/**
* 获取列列表数据
*/
async getList(){
let data = await this.field('title, content').where({
id: ['>', 100]
}).order('id DESC').select();
...
}
}

where ,
table ,
alias ,
data ,
field ,
order ,
limit ,
page , sql limit
group , group
having , having
join , join
union , union
distinct , distinct
cache

Model -> API


src/config/adapter/model.js
js module.exports = { type: 'mysql', common: { log_sql: true, log_connect: true, },
adapter: { mysql: { host: '127.0.0.1', port: '', database: '', //数据库名称 user: '',
//数据库帐号 password: '', //数据库密码 prefix: 'think_', encoding: 'utf8' } } };
src/config/adater.js exports.model = require('./adapter/model.js')

think_ user
think_user user_group think_user_group

tablePrefix
tableName

module.exports = class extends think.Model {


constructor(...args) {
super(...args);
this.tablePrefix = ''; //将数据表前缀设置为空
this.tableName = 'user2'; //将对应的数据表名设置为 user2
}
}

id Primary Key id

module.exports = class extends think.Mode {


constructor(...args) {
super(...args);
this.pk = 'user_id'; //将主键字段设置为 user_id
}
}
count sum min max

//src/config/adapter/model.js
module.exports = {
type: 'mysql',
mysql: {
host: '127.0.0.1',
port: '',
database: 'test1',
user: 'root1',
password: 'root1',
prefix: '',
encoding: 'utf8'
},
mysql2: {
type: 'mysql', //这⾥里里需要将 type 重新设置为 mysql
host: '127.0.0.1',
port: '',
database: 'test2',
user: 'root2',
password: 'root2',
prefix: '',
encoding: 'utf8'
}
}

注意 mysql2 type mysql

module.exports = class extends think.Controller {


indexAction(){
let model1 = this.model('test'); //
let model2 = this.model('test', 'mysql2'); //指定使⽤用 mysql2 的配置连接数据库
}
}

ThinkJS
parser src/config/adapter/model.js
//读配置
const MYSQL_READ = {
host: '10.0.10.1',
}
//写配置
const MYSQL_WRITE = {
host: '10.0.10.2'
}
module.exports = {
host: '127.0.0.1',
adapter: {
mysql: {
parser(options) { //mysql 的配置解析⽅方法
let sql = options.sql; //接下来要执⾏行行的 SQL 语句句
if(sql.indexOf('SELECT') === 0){ //SELECT 查询
return MYSQL_READ;
}
return MYSQL_WRITE;
}
}
}
}

parser options SQL parser

CRUD

add id

module.exports = class extends think.Controller {


async addAction(){
let model = this.model('user');
let insertId = await model.add({name: 'xxx', pwd: 'yyy'});
}
}

mysql CURRENT_TIMESTAMP
exp
export default class extends think.controller.base {
async addAction(){
let model = this.model('user');
let insertId = await model.add({
name: 'test',
time: ['exp', 'CURRENT_TIMESTAMP()']
});
}
}

addMany

module.exports = class extends think.Controller {


async addAction(){
let model = this.model('user');
let insertId = await model.addMany([
{name: 'xxx', pwd: 'yyy'},
{name: 'xxx1', pwd: 'yyy1'}
]);
}
}

thenAdd

thenAdd

module.exports = class extends think.Controller {


async addAction(){
let model = this.model('user');
//第⼀一个参数为要添加的数据,第⼆二个参数为添加的条件,根据第⼆二个参数的条件查询⽆无相关记录时才会
添加
let result = await model.thenAdd({name: 'xxx', pwd: 'yyy'}, {name: 'xxx'});
// result returns {id: 1000, type: 'add'} or {id: 1000, type: 'exist'}
}
}
update

update

module.exports = class extends think.Controller {


async updateAction(){
let model = this.model('user');
let affectedRows = await model.where({name: 'thinkjs'}).update({email: 'admin@
thinkjs.org'});
}
}

where
1=1 where

module.exports = class extends think.Controller {


async updateAction(){
let model = this.model('user');
let affectedRows = await model.where('1=1').update({email: '[email protected]'
});
}
}

exp

export default class extends think.controlle.base {


async updateAction(){
let model = this.model('user');
let affectedRows = await model.where('1=1').update({
email: '[email protected]',
view_nums: ['exp', 'view_nums+1'],
update_time: ['exp', 'CURRENT_TIMESTAMP()']
});
}
}

increment

increment

module.exports = class extends think.Model {


updateViewNums(id){
return this.where({id: id}).increment('view_nums', 1); //将阅读数加 1
}
}

decrement

decrement

module.exports = class extends think.Model {


updateViewNums(id){
return this.where({id: id}).decrement('coins', 10); //将⾦金金币减 10
}
}

find

module.exports = class extends think.Controller {


async listAction(){
let model = this.model('user');
let data = await model.where({name: 'thinkjs'}).find();
//data returns {name: 'thinkjs', email: '[email protected]', ...}
}
}

{} think.isEmpty

select

module.exports = class extends think.Controller {


async listAction(){
let model = this.model('user');
let data = await model.limit(2).select();
//data returns [{name: 'thinkjs', email: '[email protected]'}, ...]
}
}

[] think.isEmpty

countSelect

module.exports = class extends think.Controller {


async listAction(){
let model = this.model('user');
let data = await model.page(this.get('page'), 10).countSelect();
}
}

{
numsPerPage: 10, //每⻚页显示的条数
currentPage: 1, //当前⻚页
count: 100, //总条数
totalPages: 10, //总⻚页数
data: [{ //当前⻚页下的数据列列表
name: 'thinkjs',
email: '[email protected]'
}, ...]
}

true
false countSelect(true) countSelect(false)

countSelect(1000)
1000

count
count

module.exports = class extends think.Model {


getMin(){
//查询 status 为 publish 的总条数
return this.where({status: 'publish'}).count();
}
}

sum

sum

module.exports = class extends think.Model {


getMin(){
//查询 status 为 publish 字段 view_nums 的总和
return this.where({status: 'publish'}).sum('view_nums');
}
}

max

max

module.exports = class extends think.Model {


getMin(){
//查询 status 为 publish,字段 comments 的最⼤大值
return this.where({status: 'publish'}).max('comments');
}
}

min

min

module.exports = class extends think.Model {


getMin(){
//查询 status 为 publish,字段 comments 的最⼩小值
return this.where({status: 'publish'}).min('comments');
}
}
cache

module.exports = class extends think.Model {


getList(){
//设定缓存 key 和缓存时间
return this.cache('get_list', 3600).where({id: {'>': 100}}).select();
}
}

key get_list

key SQL key

module.exports = class extends think.Model {


getList(){
//只设定缓存时间
return this.cache(3600).where({id: {'>': 100}}).select();
}
}

cache src/common/config/db.js

module.exports = {
cache: {
on: true,
type: '',
timeout: 3600
}
}

on cache
type Adapter -> Cache
timeout
delete

module.exports = class extends think.Controller {


async deleteAction(){
let model = this.model('user');
let affectedRows = await model.where({id: ['>', 100]}).delete();
}
}

API -> model

Mysql InnoDB BDB Mysql


InnoDB BDB

SQLite

startTrans commit rollback 3

startTrans
commit
rollback

module.exports = class extends think.Controller {


async indexAction(){
let model = this.model('user');
try{
await model.startTrans();
let userId = await model.add({name: 'xxx'});
let insertId = await this.model('user_group').add({user_id: userId, group_id
: 1000});
await model.commit();
}catch(e){
await model.rollback();
}
}
}

transaction

startTrans commit rollback 3


transaction

module.exports = class extends think.Controller {


async indexAction(self){
let model = this.model('user');
let insertId = await model.transaction(async () => {
let userId = await model.add({name: 'xxx'});
return await self.model('user_group').add({user_id: userId, group_id: 1000})
;
});
}
}

transaction

db

indexAction(){
let model = this.model('user');
await model.transaction(async () => {
//通过 db ⽅方法将 user 模型的数据库连接传递给 article 模型
let model2 = this.model('article').db(model.db());
// do something
})
}

ThinkJS
4

think.Model.Relation.HAS_ONE
think.Model.Relation.BELONG_TO
think.Model.Relation.HAS_MANY
think.Model.Relation.MANY_TO_MANY

thinkjs model [name] --relation

thinkjs model post --relation

src/model/post.js

relation

module.exports = class extends think.Model.Relation {


constructor(...args) {
super(...args);
//通过 relation 属性指定关联关系,可以指定多个关联关系
this.relation = {
cate: {},
comment: {}
};
}
}

ES7 relation

module.exports = class extends think.Model.Relation {

//直接定义 relation 属性
relation = {
cate: {},
comment: {}
};
}
module.exports = class extends think.Model.Relation {
constructor(...args){
super(...args);
this.relation = {
cate: {
type: think.Model.Relation.MANY_TO_MANY, //relation type
model: '', //model name
name: 'profile', //data name
key: 'id',
fKey: 'user_id', //forign key
field: 'id,name',
where: 'name=xx',
order: '',
limit: '',
rModel: '',
rfKey: ''
},
};
}
}

type
model key cate
name key cate
key key
fKey key
field field fKey
where where
order order
limit limit
page page
rModel
rfKey key

module.exports = class extends think.Model.Relation {


constructor(...args){
super(...args);
this.relation = {
cate: think.Model.Relation.MANY_TO_MANY
};
}
}

HAS_ONE

user info key id


fKey user_id

module.exports = class extends think.Model.Relation {


init(..args){
super(...args);
this.relation = {
info: think.Model.Relation.HAS_ONE
};
}
}

[
{
id: 1,
name: '111',
info: { //关联表⾥里里的数据信息
user_id: 1,
desc: 'info'
}
}, ...]

BELONG_TO

HAS_ONE

info user key user_id


fKey id

module.exports = class extends think.Model.Relation {


init(..args){
super(...args);
this.relation = {
user: think.Model.Relation.BELONG_TO
};
}
}

[
{
id: 1,
user_id: 1,
desc: 'info',
user: {
name: 'thinkjs'
}
}, ...
]

HAS_MANY

post comment key id


fKey post_id

module.exports = class extends think.Model.Relation {


constructor(...args){
super(...args);

this.relation = {
comment: {
type: think.Model.Relation.HAS_MANY
}
};
}
}

[{
id: 1,
title: 'first post',
content: 'content',
comment: [{
id: 1,
post_id: 1,
name: 'welefen',
content: 'first comment'
}, ...]
}, ...]

page

module.exports = class extends think.Model.Relation {


constructor(...args){
super(...args);

this.relation = {
comment: {
type: think.Model.Relation.HAS_MANY
}
};
}
getList(page){
return this.setRelation('comment', {page: page}).select();
}
}

setRelation

MANY_TO_MANY

post cate
rModel post_cate rfKey cate_id

module.exports = class extends think.Model.Relation {


constructor(...args){
super(...args);

this.relation = {
cate: {
type: think.Model.Relation.MANY_TO_MANY,
rModel: 'post_cate',
rfKey: 'cate_id'
}
};
}
}

[{
id: 1,
title: 'first post',
cate: [{
id: 1,
name: 'cate1',
post_id: 1
}, ...]
}, ...]

2 HAS_ONE BELONG_TO

relation

module.exports = class extends think.Model.Relation {


constructor(...args){
super(...args);
this.relation = {
user: {
type: think.Model.Relation.BELONG_TO,
relation: false //关联表 user 查询时关闭关联查询
}
};
}
}

module.exports = class extends think.Model.Relation {


constructor(...args){
super(...args);
this.relation = {
user: {
type: think.Model.Relation.BELONG_TO,
relation: 'info' //关联表 user 查询时关闭对 info 模型的关联关系
}
};
}
}

setRelation

setRelation(false)

module.exports = class extends think.Model.Relation {


constructor(...args){
super(...args);
this.relation = {
comment: think.Model.Relation.HAS_MANY,
cate: think.Model.Relation.MANY_TO_MANY
};
}
getList(){
return this.setRelation(false).select();
}
}

setRelation('comment') comment

module.exports = class extends think.Model.Relation {


constructor(...args){
super(...args);
this.relation = {
comment: think.Model.Relation.HAS_MANY,
cate: think.Model.Relation.MANY_TO_MANY
};
}
getList2(){
return this.setRelation('comment').select();
}
}
setRelation('comment', false) comment

module.exports = class extends think.Model.Relation {


constructor(...args){
super(...args);
this.relation = {
comment: think.Model.Relation.HAS_MANY,
cate: think.Model.Relation.MANY_TO_MANY
};
}
getList2(){
return this.setRelation('comment', false).select();
}
}

setRelation(true)

module.exports = class extends think.Model.Relation {


constructor(...args){
super(...args);
this.relation = {
comment: think.Model.Relation.HAS_MANY,
cate: think.Model.Relation.MANY_TO_MANY
};
}
getList2(){
return this.setRelation(true).select();
}
}

field

field
module.exports = class extends think.Model.Relation {
constructor(...args){
super(...args);
this.relation = {
user: {
type: think.Model.Relation.BELONG_TO,
field: 'id,name,email' //必须要包含关联字段 id
}
};
}
}

field

module.exports = class extends think.Model.Relation {


constructor(...args){
super(...args);
this.relation = {
user: {
type: think.Model.Relation.BELONG_TO,
field: model => model._relationField
}
};
}
selectData(relationfield){
//将要查询的关联字段设置到⼀一个私有属性中,便便于动态设置 field ⾥里里获取
this._relationField = relationfield;
return this.select();
}
}

model

where

where

module.exports = class extends think.Model.Relation {


constructor(...args){
super(...args);
this.relation = {
user: {
type: think.Model.Relation.BELONG_TO,
where: {
grade: 1 //只查询关联表⾥里里 grade = 1 的数据
}
}
};
}
}

where

module.exports = class extends think.Model.Relation {


constructor(...args){
super(...args);
this.relation = {
user: {
type: think.Model.Relation.BELONG_TO,
where: model => model._relationWhere
}
};
}
selectData(relationWhere){
this._relationWhere = relationWhere;
return this.select();
}
}

model

page

page page limit

module.exports = class extends think.Model.Relation {


constructor(...args){
super(...args);
this.relation = {
user: {
type: think.Model.Relation.BELONG_TO,
page: [1, 15] //第⼀一⻚页,每⻚页 15 条
}
};
}
}

module.exports = class extends think.Model.Relation {


constructor(...args){
super(...args);
this.relation = {
user: {
type: think.Model.Relation.BELONG_TO,
page: model => model._relationPage
}
};
}
selectData(page){
this._relationPage = [page, 15];
return this.select();
}
}

model

limit

limit

module.exports = class extends think.Model.Relation {


constructor(...args){
super(...args);
this.relation = {
user: {
type: think.Model.Relation.BELONG_TO,
limit: [10] //限制 10 条
}
};
}
}

limit

module.exports = class extends think.Model.Relation {


constructor(...args){
super(...args);
this.relation = {
user: {
type: think.Model.Relation.BELONG_TO,
limit: model => model._relationLimit
}
};
}
selectData(){
this._relationLimit = [1, 15];
return this.select();
}
}

model

page limit page limit

order

order

module.exports = class extends think.Model.Relation {


constructor(...args){
super(...args);
this.relation = {
user: {
type: think.Model.Relation.BELONG_TO,
order: 'level DESC'
}
};
}
}

order

module.exports = class extends think.Model.Relation {


constructor(...args){
super(...args);
this.relation = {
user: {
type: think.Model.Relation.BELONG_TO,
order: model => model._relationOrder
}
};
}
selectData(){
this._relationOrder= 'level DESC';
return this.select();
}
}

model
id int user_id int

Mysql

ThinkJS Mysql https://www.npmjs.com/package/mysql

Mysql
src/config/adapter/model.js

module.exports = {
common: {
connectionLimit: 10 //建⽴立 10 个连接
}
}

socketPath

host port Mysql unix domain socket Mysql

module.exports = {
common: {
socketPath: '/tmp/mysql.socket'
}
}

SSL options

SSL
const fs = require('fs');
module.exports = {
common: {
ssl: {
ca: fs.readFileSync(__dirname + '/mysql-ca.crt')
}
}
}

emoji

utf8 utf8 emoji emoji


utf8mb4

src/config/adapter/model.js encoding utf8mb4

module.exports = {
common: {
encoding: 'utf8mb4'
}
}

model

think.Model

module.exports = class extends think.Model {


getList(){

}
}

model.pk

id
model.name

for/bar/app/home/model/user.js user

model.tablePrefix

think_

model.tableName

model.schema

model.indexes

model.config

model._db

model._data

model._options
model.model(name, options, module)

name {String}
options {Object}
module {String}
return {Object}

module.exports = class extends think.Model {


async getList(){
//获取 user 模型实例例
let instance = this.model('user');
let list = await instance.select();
let ids = list.map(item => {
return item.id;
});
let data = await this.where({id: ['IN', ids]}).select();
return data;
}
}

model.getTablePrefix()

return {string}

model.getConfigKey()

return {String}

key db

model.db()

return {Object}

db

model.getModelName()

return {String}
model.getTableName()

return {String}

model.cache(key, timeout)

key {String} key


timeout {Number}
return {this}

key

module.exports = class extends think.Model {


getList(){
return this.cache('getList', 1000).where({id: {'>': 100}}).select();
}
}

key

module.exports = class extends think.Model {


getList(){
return this.cache(1000).where({id: {'>': 100}}).select();
}
}

module.exports = class extends think.Model {


getList(){
return this.cache({
key: 'getList',
timeout: 1000,
type: 'file' //使⽤用⽂文件⽅方式缓存
}).where({id: {'>': 100}}).select();
}
}
model.limit(offset, length)

offset {Number}
length {Number}
return {this}

module.exports = class extends think.Model {


getList(){
//查询20条数据
return this.limit(20).where({id: {'>': 100}}).select();
}
}

module.exports = class extends think.Model {


getList(){
//从起始位置100开始查询20调数据
return this.limit(100, 20).where({id: {'>': 100}}).select();
}
}

module.exports = class extends think.Model {


getList(){
//从起始位置100开始查询20调数据
return this.limit([100, 20]).where({id: {'>': 100}}).select();
}
}

model.page(page, listRows)

page {Number} 1
listRows {Number}
return {this}
limit

module.exports = class extends think.Model {


getList(){
//查询第 2 ⻚页数据,每⻚页 10 条数据
return this.page(2, 10).where({id: {'>': 100}}).select();
}
}

module.exports = class extends think.Model {


getList(){
//查询第 2 ⻚页数据,每⻚页 10 条数据
return this.page([2, 10]).where({id: {'>': 100}}).select();
}
}

model.where(where)

where {String | Object} where


return {this}

where _logic AND _complex


1. mongo model mongo where model.mongo where

2. where Logic

module.exports = class extends think.Model {


where1(){
//SELECT * FROM `think_user`
return this.where().select();
}
where2(){
//SELECT * FROM `think_user` WHERE ( `id` = 10 )
return this.where({id: 10}).select();
}
where3(){
//SELECT * FROM `think_user` WHERE ( id = 10 OR id < 2 )
return this.where('id = 10 OR id < 2').select();
}
where4(){
//SELECT * FROM `think_user` WHERE ( `id` != 10 )
return this.where({id: ['!=', 10]}).select();
}
}

null

module.exports = class extends think.Model {


where1(){
//SELECT * FROM `think_user` where ( title IS NULL );
return this.where({title: null}).select();
}
where2(){
//SELECT * FROM `think_user` where ( title IS NOT NULL );
return this.where({title: ['!=', null]}).select();
}
}

EXP

ThinkJS
EXP

module.exports = class extends think.Model {


where1(){
//SELECT * FROM `think_user` WHERE ( (`name` ='name') )
return this.where({name: ['EXP', "=\"name\""]}).select();
}
}

LIKE

module.exports = class extends think.Model {


where1(){
//SELECT * FROM `think_user` WHERE ( `title` NOT LIKE 'welefen' )
return this.where({title: ['NOTLIKE', 'welefen']}).select();
}
where2(){
//SELECT * FROM `think_user` WHERE ( `title` LIKE '%welefen%' )
return this.where({title: ['like', '%welefen%']}).select();
}
//like 多个值
where3(){
//SELECT * FROM `think_user` WHERE ( (`title` LIKE 'welefen' OR `title` LIKE '
suredy') )
return this.where({title: ['like', ['welefen', 'suredy']]}).select();
}
//多个字段或的关系 like ⼀一个值
where4(){
//SELECT * FROM `think_user` WHERE ( (`title` LIKE '%welefen%') OR (`content`
LIKE '%welefen%') )
return this.where({'title|content': ['like', '%welefen%']}).select();
}
//多个字段与的关系 Like ⼀一个值
where5(){
//SELECT * FROM `think_user` WHERE ( (`title` LIKE '%welefen%') AND (`content`
LIKE '%welefen%') )
return this.where({'title&content': ['like', '%welefen%']}).select();
}
}

IN

module.exports = class extens think.Model {


where1(){
//SELECT * FROM `think_user` WHERE ( `id` IN ('10','20') )
return this.where({id: ['IN', '10,20']}).select();
}
where2(){
//SELECT * FROM `think_user` WHERE ( `id` IN (10,20) )
return this.where({id: ['IN', [10, 20]]}).select();
}
where3(){
//SELECT * FROM `think_user` WHERE ( `id` NOT IN (10,20) )
return this.where({id: ['NOTIN', [10, 20]]}).select();
}
}

BETWEEN

module.exports = class extens think.Model {


where1(){
//SELECT * FROM `think_user` WHERE ( (`id` BETWEEN 1 AND 2) )
return this.where({id: ['BETWEEN', 1, 2]}).select();
}
where2(){
//SELECT * FROM `think_user` WHERE ( (`id` BETWEEN '1' AND '2') )
return this.where({id: ['between', '1,2']}).select();
}
}
module.exports = class extends think.Model {
where1(){
//SELECT * FROM `think_user` WHERE ( `id` = 10 ) AND ( `title` = 'www' )
return this.where({id: 10, title: "www"}).select();
}
//修改逻辑为 OR
where2(){
//SELECT * FROM `think_user` WHERE ( `id` = 10 ) OR ( `title` = 'www' )
return this.where({id: 10, title: "www", _logic: 'OR'}).select();
}
//修改逻辑为 XOR
where2(){
//SELECT * FROM `think_user` WHERE ( `id` = 10 ) XOR ( `title` = 'www' )
return this.where({id: 10, title: "www", _logic: 'XOR'}).select();
}
}

module.exports = class extends think.Model {


where1(){
//SELECT * FROM `think_user` WHERE ( `id` > 10 AND `id` < 20 )
return this.where({id: {'>': 10, '<': 20}}).select();
}
//修改逻辑为 OR
where2(){
//SELECT * FROM `think_user` WHERE ( `id` < 10 OR `id` > 20 )
return this.where({id: {'<': 10, '>': 20, _logic: 'OR'}}).select()
}
}

module.exports = class extends think.Model {


where1(){
//SELECT * FROM `think_user` WHERE ( `title` = 'test' ) AND ( ( `id` IN (1,2,
3) ) OR ( `content` = 'www' ) )
return this.where({
title: 'test',
_complex: {id: ['IN', [1, 2, 3]],
content: 'www',
_logic: 'or'
}
}).select()
}
}

model.field(field)

field {String | Array}


return {this}

module.exports = class extends think.controller.base {


async indexAction(){
let model = this.model('user');
//设置要查询的字符串串,字符串串⽅方式,多个⽤用逗号隔开
let data = await model.field('name,title').select();
}
}

SQL

module.exports = class extends think.controller.base {


//字段⾥里里调⽤用 SQL 函数
async listAction(){
let model = this.model('user');
let data = await model.field('id, INSTR(\'30,35,31,\',id + \',\') as d').selec
t();
}
}

module.exports = class extends think.controller.base {


async indexAction(){
let model = this.model('user');
//设置要查询的字符串串,数组⽅方式
let data = await model.field(['name','title']).select();
}
}
model.fieldReverse(field)

field {String | Array}


return {this}

model.table(table, hasPrefix)

table {String}
hasPrefix {Boolean} table
return {this}

SQL

module.exports = class extends think.Model {


getList(){
return this.table('test', true).select();
}
}

SQL

module.exports = class extends think.Model {


async getList(){
let sql = await this.model('group').group('name').buildSql();
let data = await this.table(sql).select();
return data;
}
}

model.union(union, all)

union {String | Object} SQL


all {Boolean} UNION ALL
return {this}

SQL
module.exports = class extends think.Model {
getList(){
//SELECT * FROM `think_user` UNION (SELECT * FROM think_pic2)
return this.union('SELECT * FROM think_pic2').select();
}
}

module.exports = class extends think.Model {


getList(){
//SELECT * FROM `think_user` UNION ALL (SELECT * FROM `think_pic2`)
return this.union({table: 'think_pic2'}, true).select();
}
}

model.join(join)

join {String | Object | Array} LEFT JOIN


return {this}

module.exports = class extends think.Model {


getList(){
//SELECT * FROM `think_user` LEFT JOIN think_cate ON think_group.cate_id=think
_cate.id
return this.join('think_cate ON think_group.cate_id=think_cate.id').select();
}
}

module.exports = class extends think.Model {


getList(){
//SELECT * FROM `think_user` LEFT JOIN think_cate ON think_group.cate_id=think
_cate.id RIGHT JOIN think_tag ON think_group.tag_id=think_tag.id
return this.join([
'think_cate ON think_group.cate_id=think_cate.id',
'RIGHT JOIN think_tag ON think_group.tag_id=think_tag.id'
]).select();
}
}

module.exports = class extends think.Model {


getList(){
//SELECT * FROM `think_user` INNER JOIN `think_cate` AS c ON think_user.`cate_
id`=c.`id`
return this.join({
table: 'cate',
join: 'inner', //join ⽅方式,有 left, right, inner 3 种⽅方式
as: 'c', // 表别名
on: ['cate_id', 'id'] //ON 条件
}).select();
}
}

JOIN

module.exports = class extends think.Model {


getList(){
//SELECT * FROM think_user AS a LEFT JOIN `think_cate` AS c ON a.`cate_id`=c.`
id` LEFT JOIN `think_group_tag` AS d ON a.`id`=d.`group_id`
return this.alias('a').join({
table: 'cate',
join: 'left',
as: 'c',
on: ['cate_id', 'id']
}).join({
table: 'group_tag',
join: 'left',
as: 'd',
on: ['id', 'group_id']
}).select()
}
}

module.exports = class extends think.Model {


getList(){
//SELECT * FROM `think_user` LEFT JOIN `think_cate` ON think_user.`id`=think_c
ate.`id` LEFT JOIN `think_group_tag` ON think_user.`id`=think_group_tag.`group_id`
return this.join({
cate: {
on: ['id', 'id']
},
group_tag: {
on: ['id', 'group_id']
}
}).select();
}
}

module.exports = class extends think.Model {


getList(){
//SELECT * FROM think_user AS a LEFT JOIN `think_cate` AS c ON a.`id`=c.`id` L
EFT JOIN `think_group_tag` AS d ON a.`id`=d.`group_id`
return this.alias('a').join({
cate: {
join: 'left', // 有 left,right,inner 3 个值
as: 'c',
on: ['id', 'id']
},
group_tag: {
join: 'left',
as: 'd',
on: ['id', 'group_id']
}
}).select()
}
}

ON

module.exports = class extends think.Model {


getList(){
//SELECT * FROM `think_user` LEFT JOIN `think_cate` ON think_user.`id`=think_c
ate.`id` LEFT JOIN `think_group_tag` ON think_user.`id`=think_group_tag.`group_id`
LEFT JOIN `think_tag` ON (think_user.`id`=think_tag.`id` AND think_user.`title`=t
hink_tag.`name`)
return this.join({
cate: {on: 'id, id'},
group_tag: {on: ['id', 'group_id']},
tag: {
on: { // 多个字段的 ON
id: 'id',
title: 'name'
}
}
}).select()
}
}
table SQL

module.exports = class extends think.Model {


async getList(){
let sql = await this.model('group').buildSql();
//SELECT * FROM `think_user` LEFT JOIN ( SELECT * FROM `think_group` ) ON thin
k_user.`gid`=( SELECT * FROM `think_group` ).`id`
return this.join({
table: sql,
on: ['gid', 'id']
}).select();
}
}

model.order(order)

order {String | Array | Object}


return {this}

module.exports = class extends think.Model {


getList(){
//SELECT * FROM `think_user` ORDER BY id DESC, name ASC
return this.order('id DESC, name ASC').select();
}
getList1(){
//SELECT * FROM `think_user` ORDER BY count(num) DESC
return this.order('count(num) DESC').select();
}
}

module.exports = class extends think.Model {


getList(){
//SELECT * FROM `think_user` ORDER BY id DESC,name ASC
return this.order(['id DESC', 'name ASC']).select();
}
}
module.exports = class extends think.Model {
getList(){
//SELECT * FROM `think_user` ORDER BY `id` DESC,`name` ASC
return this.order({
id: 'DESC',
name: 'ASC'
}).select();
}
}

model.alias(tableAlias)

tableAlias {String}
return {this}

module.exports = class extends think.Model {


getList(){
//SELECT * FROM think_user AS a;
return this.alias('a').select();
}
}

model.having(having)

having {String} having


return {this}

having

module.exports = class extends think.Model {


getList(){
//SELECT * FROM `think_user` HAVING view_nums > 1000 AND view_nums < 2000
return this.having('view_nums > 1000 AND view_nums < 2000').select();
}
}

model.group(group)

group {String}
return {this}

module.exports = class extends think.Model {


getList(){
//SELECT * FROM `think_user` GROUP BY `name`
return this.group('name').select();
}
}

model.distinct(distinct)

distinct {String}
return {this}

module.exports = class extends think.Model {


getList(){
//SELECT DISTINCT `name` FROM `think_user`
return this.distinct('name').select();
}
}

model.explain(explain)

explain {Boolean} explain


return {this}

SQL explain SQL

model.optionsFilter(options)

model.dataFilter(data)

data {Object | Array}


model.beforeAdd(data)

data {Object}

model.afterAdd(data)

data {Object}

model.afterDelete(data)

model.beforeUpdate(data)

data {Object}

model.afterUpdate(data)

data {Object}

model.afterFind(data)

data {Object}
return {Object | Promise}

find

model.afterSelect(data)

data [Array]
return {Array | Promise}

select

model.data(data)
data {Object}

model.options(options)

options {Object}

module.exports = class extends think.Model {


getList(){
return this.options({
where: 'id = 1',
limit: [10, 1]
}).select();
}
}

model.close()

model.getSchema(table)

table {String}
return {Promise}

model.getTableFields(table)

已废弃 model.getSchema

model.getLastSql()

return {String}

SQL

model.buildSql()
return {Promise}

SQL

model.parseOptions(oriOpts, extraOptions)

oriOpts {Object}
extraOptions {Object}
return {Promise}

model.getPk()

return {Promise}

pk Promise

model.parseType(field, value)

field {String}
value {Mixed}
return {Mixed}

value

model.parseData(data)

data {Object}
return {Object}

parseType

model.add(data, options, replace)

data {Object}
options {Object}
replace {Boolean}
return {Promise} ID
model.thenAdd(data, where)

data {Object}
where {Object} where
return {Promise}

where

model.addMany(dataList, options, replace)

dataList {Array}
options {Object}
replace {Boolean}
return {Promise} ID

model.delete(options)

options {Object}
return {Promise}

id 7

model.delete({
where: {id: 7}
});

model.update(data, options)

data {Object}
options {Object}
return {Promise}

model.thenUpdate(data, where)

data {Object}
where {Object} where
return {Promise}

where

updateMany(dataList, options)

dataList {Array}
options {Object}
return {Promise}

dataList

model.increment(field, step)

field {String}
step {Number} 1
return {Promise}

model.decrement(field, step)

field {String}
step {Number} 1
return {Promise}

model.find(options)

options {Object}
return {Promise}

{}

model.select(options)

options {Object}
return {Promise}

[]
model.countSelect(options, pageFlag)

options {Object}
pageFlag {Boolean} true false

return {Promise}

page

module.exports = class extends think.controller.base {


async listAction(){
let model = this.model('user');
let data = await model.page(this.get('page')).countSelect();
}
}

{
numsPerPage: 10, //每⻚页显示的条数
currentPage: 1, //当前⻚页
count: 100, //总条数
totalPages: 10, //总⻚页数
data: [{ //当前⻚页下的数据列列表
name: "thinkjs",
email: "[email protected]"
}, ...]
}

model.getField(field, one)

field {String}
one {Boolean | Number}
return {Promise}

model.count(field)

field {String}
return {Promise}
model.sum(field)

field {String}
return {Promise}

model.min(field)

field {String}
return {Promise}

model.max(field)

field {String}
return {Promise}

model.avg(field)

field {String}
return {Promise}

model.query(...args)

return {Promise}

SQL

model.execute(...args)

return {Promise}

SQL

model.parseSql(sql, ...args)
sql {String} SQL
return {String}

SQL util.format SQL SQL __TABLENAME__

module.exports = class extends think.Model {


getSql(){
let sql = 'SELECT * FROM __GROUP__ WHERE id=%d';
sql = this.parseSql(sql, 10);
//sql is SELECT * FROM think_group WHERE id=10
}
}

model.startTrans()

return {Promise}

model.commit()

return {Promise}

model.rollback()

return {Promise}

model.transaction(fn)

fn {Function}
return {Promise}

Promise

module.exports = class extends think.Model {


updateData(data){
return this.transaction(async () => {
let insertId = await this.add(data);
let result = await this.model('user_cate').add({user_id: insertId, cate_id:
100});
return result;
})
}
}

--mode=multi

thinkjs new demo --mode=multi

src/common
src/home
src/xxx

You might also like