首页 » 网站推广 » PHP案例封装DB类技巧_为Nodejs加一个DB类

PHP案例封装DB类技巧_为Nodejs加一个DB类

访客 2024-10-31 0

扫一扫用手机浏览

文章目录 [+]

而在学习或者利用Node.js的时候,不免会与MySQL等数据库进行连接交互。
而笔者在学习Node之前,利用过ThinkPHP5,个中内置的DB类让我半吊子“后端”用起来十分舒畅,个中的链式调用更是方便无比。

那么此文,我们也考试测验着去封装一个DB类,毕竟手写SQL太随意马虎涌现缺点啦。

PHP案例封装DB类技巧_为Nodejs加一个DB类

明确需求

这个环节有点像PM跟我们阐述一个功能需求。
假设已经存在这么一个类,我们希望这个类是如何为我所用的?以下为我自己的几个需求,后面的编码就从这几个需求出发,一步步完善我们的类即可。

PHP案例封装DB类技巧_为Nodejs加一个DB类
(图片来自网络侵删)
链式调用

例如TP5中,如果要查询user表中id为1的用户,我们常常这样子写:

DB::table('user')->where('id',1)->find();

一开始得确定传入的表名,也算是我们约定的一个规范吧。
而中间环节可以有多个where,类自动帮我们拼接好查询条件,在末了调用的该当因此下几个常用的方法:

•find 查询一条记录•select 查询符合条件的记录•count 返回记录的条数•update 更新操作•delete 删除操作•insert 插入操作

例如如果我们的类写好了,描述上述语法,我希望这样利用:

DB.table('user').where('id',1).find();基于Promise封装

我们知道Node里面查询数据库是一个异步操作,而我在利用这个类的时候,希望越简洁越好。
不要让我去思考一些异步的流程。
比如可以像下面这样:

const result = await DB.table('user').select();

这种利用async/await的写法我个人是比较喜好的,看起来代码逻辑较为清晰一些。

其他的小偏好

find/select方法我希望可以按需取字段,insert/update的时候我希望传入一个Object来描述,where传参的时候如果不穿操作符,默认便是等号,还能支持原生SQL查询......

常用方法编码

那大概捋了一下思路之后,我们就开始进行编码吧。
先搭起来一个架子:

class Orm { constructor(debug = 0) { this.sql = '' this._table = '' this.filter = '' this.debug = debug } count() {} find() {} select() {} insert() {} delete() {} update() {} where(){} table(){}}module.exports = { Orm}

上述除了待会要实现的详细方法之外,还有三个我们这个类所用到的变量。

•sql 末了拼接成的SQL语句•_table 一开始暂存的表名•filter 过滤条件字符串•debug debug模式,如果为1则会打出完全SQL语句

而在利用这个类的时候只管即便是单例模式,这样与JS单线程的特点结合起来,就不会涌现什么冲突。

select 方法实现

在真正开始动手实现我们的第一个查询方法时,还是回到我们之前说的。
如果这个类写好了,我们希望若何去利用它。
我希望像下述一样去利用:

const Orm = require('./orm/index').Ormconst orm = new Orm()async function select() { const result = await orm.table('good').select() console.log('result',result)}

基于上述最大略版本的select方法,我们可以开始以下的编码。
首先table方法的实现便是缓存一下表名即可,而这些须要链式调用的方法,只需在末了加上一句return this即可。

table(table){ this._table = table return this}

select的详细实现如下,实在便是拼接一下字符串。
传列名则按需取字段,不传就取所有字段。

select(..._cols) { let cols = [..._cols] if (cols.length != 0) { let c = '' for (let i = 0; i < cols.length; i++) { let char = cols[i] if (i != cols.length - 1) { c += `${char},` } else { c += `${char}` } } this.sql = `SELECT ${c} FROM ${this._table} ${this.filter}` } else { this.sql = `SELECT FROM ${this._table} ${this.filter}` } //run 方法则为真正去跟数据库交互的方法 return this.run()}

find方法与select方法的差异只是find方法在末了加上了LIMIT 1而已,其他详细实现基本一样

实现中,末了的CURD方法都会调到这个run方法,让我们来看一下这个run方法的实现。
真正与mysql交互前,还需安装好mysql驱动。

//dbConfig.jsmodule.exports = { mysql: { host: 'localhost', user: 'root', password: 'your mysql psw', database: 'shop', port: 3306 }};

const mysql = require('mysql')const dbConfig = require('./dbConfig')//创建一个mysql连接池const pool = mysql.createPool(dbConfig.mysql)run() { let _sql = this.sql //debug模式打印出SQL语句 if(this.debug) console.log(_sql) let table = this._table //把稳在进行数据库查询的前一刻,该当把之前缓存的字符串清空掉。
this.done() //基于Promise封装 return new Promise((resolve, reject) => { if (!table) { reject('表名不可为空') } else { //进行数据库查询 pool.getConnection((err, con) => { if (err) { reject(err) } else { con.query(_sql, (err, result) => { if (err) { reject(err) } else { resolve(result) con.release() } }) } }) } })}done(){ this.sql = '' this._table = '' this.filter = ''}

末了再来总结一下流程:

1.暂存表名2.拼装SQL3.return this担保链式调用4.Promise+async/await担保更友好的利用形式

理解了大概的套路之后,之后的编码就会更加顺利了。
我们再来实现多几个方法。

where实现

在利用where的时候,不自觉地就往利用过的TP框架上面靠了。
有一个小偏好便是,当传参只有两个时,默认的操作符是'='。
例如

DB.table('user').where('id',1).select()//等同于DB.table('user').where('id','=','1').select()

where(...arg) { let arr = [...arg] let column = arr[0] || null, op = arr[1] || null, val = arr[2] || null if (arr.length == 2) { column = arr[0] val = arr[1] op = '=' } if (this.filter) { this.filter += ` AND ${column} ${op} '${val}'` } else { this.filter = `WHERE ${column} ${op} '${val}'` } return this}

where方法的详细实现实在便是把传入的过滤字符串拼装filter变量里面,再末了做CURD操作时,将filter拼装上去即可。

insert实现

insert 方法我希望像如下这样利用:

let result = await orm.table('user').insert({ name:'张三', age:18})console.log(result)

那么编写的时候,把工具遍历完key和value,依次拼装即可。

insert(obj) { let keys = '', values = '' let objArr = Object.keys(obj) for (let i = 0; i < objArr.length; i++) { let key = objArr[i] let val = obj[key] if (i != objArr.length - 1) { keys += `${key},` //把稳 value最好用''括起来 values += `'${val}',` } else { keys += `${key}` values += `'${val}'` } } this.sql = `INSERT INTO ${this._table} (${keys}) VALUES (${values})` return this.run() }count方法

末了再贴一个count方法的实现吧

async count() { let result = await this.select() return new Promise((resolve, reject) => { resolve(result.length) })}

其他的方法大同小异就不在赘述了,可以自行拓展一些更好的方法。
拼装好SQL之后调用run即可。

末了

行文至此,感谢阅读,如果您喜好的话,可以帮忙点个like哟~

标签:

相关文章

易语言在SEO领域的应用与方法

SEO(搜索引擎优化)已经成为企业提高网站排名、获取流量的重要手段。在众多编程语言中,易语言凭借其易学易用、跨平台等特点,在SEO...

网站推广 2025-03-26 阅读1 评论0

河北电商SEO,助力企业腾飞的新引擎

电子商务已成为我国经济发展的重要引擎。河北作为我国重要的电子商务基地,拥有丰富的电商资源和庞大的消费市场。在激烈的市场竞争中,如何...

网站推广 2025-03-26 阅读1 评论0

海南,热带天堂的SEO攻略与

海南,一个位于中国最南端的热带岛屿,拥有得天独厚的自然风光和独特的文化底蕴。越来越多的游客通过网络了解海南,这也使得海南的SEO(...

网站推广 2025-03-26 阅读0 评论0