php实现带读写分离功能的MySQL类完整实例
本文实例讲述了php实现带读写分离功能的MySQL类。分享给大家供大家参考,具体如下:
概述:
1.根据sql语句判断是连接读库还是写库
2.链式调用$this->where()->get()
3.不同的主机对应不同的实例,不再多次new
具体代码如下:
<?php
classDBRWmysql
{
privatestatic$Instance=null;
private$links=array();//链接数组
private$link=null;//当前连接
public$dbType='read';
public$_host='';//数据库所在主机名
public$_database='';//当前数据库名
public$_tablename='';//当前表的表名
public$_dt='';//database.tablename
public$isRelease=0;//查询完成后是否释放
public$fields='*';
public$arrWhere=[];
public$order='';
public$arrOrder=[];
public$limit='';
public$sql='';
public$rs;//结果集
privatefunction__construct($database='',$tablename='',$isRelease=0)
{
$this->_database=$database;//databasename
$this->_tablename=$tablename;//tablename
$this->_dt="`{$this->_database}`.`{$this->_tablename}`";
$this->isRelease=$isRelease;
}
publicstaticfunctiongetInstance($database='',$tablename='',$isRelease=0)
{
if(self::$Instance==null){
self::$Instance=newDBRWmysql($database,$tablename,$isRelease);
}
self::$Instance->_database=$database;
self::$Instance->_tablename=$tablename;
self::$Instance->_dt="`{$database}`.`{$tablename}`";
self::$Instance->isRelease=$isRelease;
returnself::$Instance;
}
//如果主机没变,并且已经存在MYSQL连接,就不再创建新的连接
//如果主机改变,就再生成一个实例创建一个连接
//type=='write'或'read'
publicfunctiongetLink($type)
{
$this->dbType=$$type;
//随机选取一个数据库连接(区分读写)
$dbConfig=DBConfig::$$type;
$randKey=array_rand($dbConfig);
$config=$dbConfig[$randKey];
//链接数据库
$host=$config['host'];
$username=$config['username'];
$password=$config['password'];
if(empty($this->links[$host])){
$this->_host=$host;
$this->links[$host]=newmysqli($host,$username,$password);
if($this->links[$host]->connect_error){
$this->error($this->links[$host]->connect_error);
}
}
//初始化链接
$this->link=$this->links[$host];
$this->link->query("setnamesutf8mb4;");//支持emoji表情
$this->link->query("use{$this->_database};");
}
publicfunctiongetCurrentLinks()
{
return$this->links;
}
//析构函数
publicfunction__destruct()
{
foreach($this->linksas$v){
$v->close();
}
}
//查询封装
publicfunctionquery($sql)
{
$this->sql=$sql;
if(strpos($sql,'select')!==false){
$this->getLink('read');//读库
}else{
$this->getLink('write');//写库
}
$this->rs=$this->link->query($sql);
($this->rs===false)&&$this->error('sqlerror:'.$sql.PHP_EOL.$this->link->error);
//查询完成后释放链接,并删除链接对象
if($this->isRelease){
$this->link->close();
unset($this->links[$this->_host]);
}
return$this->rs;
}
//增
publicfunctioninsert($arrData)
{
foreach($arrDataas$key=>$value){
$fields[]=$key;
$values[]="'".$value."'";
//$fields[]='`'.$key.'`';
//$values[]="'".$value."'";
}
$strFields=implode(',',$fields);
$strValues=implode(',',$values);
$sql="insertinto{$this->_dt}($strFields)values($strValues)";
$this->query($sql);
$insert_id=$this->link->insert_id;
return$insert_id;
}
//增
publicfunctionreplace($arrData)
{
foreach($arrDataas$key=>$value){
$fields[]=$key;
$values[]="'{$value}'";
}
$strFields=implode(',',$fields);
$strValues=implode(',',$values);
$sql="replaceinto{$this->_dt}($strFields)values($strValues)";
$this->query($sql);
return$this->link->insert_id;
}
//增
//每次插入多条记录
//每条记录的字段相同,但是值不一样
publicfunctioninsertm($arrFields,$arrData)
{
foreach($arrFieldsas$v){
//$fields[]="`{$v}`";
$fields[]=$v;
}
foreach($arrDataas$v){
$data[]='('.implode(',',$v).')';
}
$strFields=implode(',',$fields);
$strData=implode(',',$data);
$sql="insertinto{$this->_dt}($strFields)values{$strData}";
$this->query($sql);
return$this->link->insert_id;
}
//删
publicfunctiondelete()
{
$where=$this->getWhere();
$limit=$this->getLimit();
$sql="deletefrom{$this->_dt}{$where}{$limit}";
$this->query($sql);
return$this->link->affected_rows;
}
//改
publicfunctionupdate($data)
{
$where=$this->getWhere();
$arrSql=array();
foreach($dataas$key=>$value){
$arrSql[]="{$key}='{$value}'";
}
$strSql=implode(',',$arrSql);
$sql="update{$this->_dt}set{$strSql}{$where}{$this->limit}";
$this->query($sql);
return$this->link->affected_rows;
}
//获取总数
publicfunctiongetCount()
{
$where=$this->getWhere();
$sql="selectcount(1)asnfrom{$this->_dt}{$where}";
$resault=$this->query($sql);
($resault===false)&&$this->error('getCounterror:'.$sql);
$arrRs=$this->rsToArray($resault);
$num=array_shift($arrRs);
return$num['n'];
}
//将结果集转换成数组返回
//如果field不为空,则返回的数组以$field为键重新索引
publicfunctionrsToArray($field='')
{
$arrRs=$this->rs->fetch_all(MYSQLI_ASSOC);//该函数只能用于php的mysqlnd驱动
$this->rs->free();//释放结果集
if($field){
$arrResult=[];
foreach($arrRsas$v){
$arrResult[$v[$field]]=$v;
}
return$arrResult;
}
return$arrRs;
}
//给字段名加上反引号
publicfunctionqw($strFields)
{
$strFields=preg_replace('#\s+#','',$strFields);
$arrNewFields=explode('',$strFields);
$arrNewFields=array_filter($arrNewFields);
foreach($arrNewFieldsas$k=>$v){
$arrNewFields[$k]='`'.$v.'`';
}
returnimplode(',',$arrNewFields);
}
//处理入库数据,将字符串格式的数据转换为...格式(未实现)
publicfunctiongetInsertData($strData)
{
//$bmap="jingdu,$jingduweidu,$weiducontent,$content";
}
//selectin
//arrData整数数组,最好是整数
publicfunctionselect_in($key,$arrData,$fields='')
{
$fields=$fields?$fields:'*';
sort($arrData);
$len=count($arrData);
$cur=0;
$pre=$arrData[0];
$new=array('0'=>array($arrData[0]));
for($i=1;$i<$len;$i++){
if(($arrData[$i]-$pre)==1){
$new[$cur][]=$arrData[$i];
}else{
$cur=$i;
$new[$cur][]=$arrData[$i];
}
$pre=$arrData[$i];
}
$arrSql=array();
foreach($newas$v){
$len=count($v)-1;
if($len){
$s=$v[0];
$e=end($v);
$sql="(select$fieldsfrom{$this->_dt}where$keybetween$sand$e)";
}else{
$s=$v[0];
$sql="(select$fieldsfrom{$this->_dt}where$key=$s)";
}
$arrSql[]=$sql;
}
$strUnion=implode('UNIONALL',$arrSql);
$res=$this->query($strUnion);
return$this->rstoarray($res);
}
//wherein
publicfunctionsetWhereIn($key,$arrData)
{
if(empty($arrData)){
$str="(`{$key}`in('0'))";
$this->addWhere($str);
return$str;
}
foreach($arrDataas&$v){
$v="'{$v}'";
}
$str=implode(',',$arrData);
$str="(`{$key}`in({$str}))";
$this->addWhere($str);
return$this;
}
//wherein
publicfunctionsetWhere($arrData)
{
if(empty($arrData)){
return'';
}
foreach($arrDataas$k=>$v){
$str="(`{$k}`='{$v}')";
$this->addWhere($str);
}
return$this;
}
//betweenand
publicfunctionsetWhereBetween($key,$min,$max)
{
$str="(`{$key}`between'{$min}'and'{$max}')";
$this->addWhere($str);
return$this;
}
//wherea>b
publicfunctionsetWhereBT($key,$value)
{
$str="(`{$key}`>'{$value}')";
$this->addWhere($str);
return$this;
}
//wherea<b
publicfunctionsetWhereLT($key,$value)
{
$str="(`{$key}`<'{$value}')";
$this->addWhere($str);
return$this;
}
//组装where条件
publicfunctionaddWhere($where)
{
$this->arrWhere[]=$where;
}
//获取最终查询用的where条件
publicfunctiongetWhere()
{
if(empty($this->arrWhere)){
return'where1';
}else{
return'where'.implode('and',$this->arrWhere);
}
}
//以逗号隔开
publicfunctionsetFields($fields)
{
$this->fields=$fields;
return$this;
}
//orderbyadesc
publicfunctionsetOrder($order)
{
$this->arrOrder[]=$order;
return$this;
}
//获取order语句
publicfunctiongetOrder()
{
if(empty($this->arrOrder)){
return'';
}else{
$str=implode(',',$this->arrOrder);
$this->order="orderby{$str}";
}
return$this->order;
}
//e.g.'0,10'
//用limit的时候可以加where条件优化:select...whereid>1234limit0,10
publicfunctionsetLimit($limit)
{
$this->limit='limit'.$limit;
return$this;
}
//直接查询sql语句,返回数组格式
publicfunctionarrQuery($sql,$field='')
{
$this->query($sql);
$this->clearQuery();
($this->rs===false)&&$this->error('selecterror:'.$sql);
return$this->rsToArray($field);
}
//如果$field不为空,则返回的结果以该字段的值为索引
//暂不支持join
publicfunctionget($field='')
{
$where=$this->getWhere();
$order=$this->getOrder();
$sql="select{$this->fields}from{$this->_dt}{$where}{$order}{$this->limit}";
return$this->arrQuery($sql,$field);
}
//获取一条记录
publicfunctiongetOne()
{
$this->setLimit(1);
$rs=$this->get();
return!empty($rs)?$rs[0]:[];
}
//获取一条记录的某一个字段的值
publicfunctiongetOneField($field)
{
$this->setFields($field);
$rs=$this->getOne();
return!empty($rs[$field])?$rs[$field]:'';
}
//获取数据集中所有某个字段的值
publicfunctiongetFields($field)
{
$this->setFields($field);
$rs=$this->get();
$result=[];
foreach($rsas$v){
$result[]=$v[$field];
}
unset($rs);
return$result;
}
//清除查询条件
//防止干扰下次查询
publicfunctionclearQuery()
{
$this->fields='*';
$this->arrWhere=[];
$this->order='';
$this->arrOrder=[];
$this->limit='';
}
//断开数据库连接
publicfunctionclose()
{
$this->link->close();
}
//事务
//自动提交开关
publicfunctionautocommit($bool)
{
$this->link->autocommit($bool);
}
//事务完成提交
publicfunctioncommit()
{
$this->link->commit();
}
//回滚
publicfunctionrollback()
{
$this->link->rollback();
}
//输出错误sql语句
publicfunctionerror($sql)
{
//if(IS_TEST){}
exit($sql);
}
}
更多关于PHP相关内容感兴趣的读者可查看本站专题:《php+mysqli数据库程序设计技巧总结》、《PHP基于pdo操作数据库技巧总结》、《PHP运算与运算符用法总结》、《PHP网络编程技巧总结》、《php面向对象程序设计入门教程》、《php字符串(string)用法总结》、《php+mysql数据库操作入门教程》及《php常见数据库操作技巧汇总》
希望本文所述对大家PHP程序设计有所帮助。