基于php实现带读写分离功能的MySQL类

墨辰丷
发布: 2023-03-29 09:20:02
原创
1186 人浏览过

这篇文章主要介绍了php实现带读写分离功能的MySQL类,具有针对mysql数据库的基本增删改查及读写分离操作的功能,涉及针对读库与写库的判断及操作技巧,需要的朋友可以参考下

具体如下:

概述:

1. 根据sql语句判断是连接读库还是写库
2. 链式调用$this->where()->get()
3. 不同的主机对应不同的实例, 不再多次new

具体代码如下:


<?php
class DBRWmysql
{
  private static $Instance = null;
  private $links = array();//链接数组
  private $link = null; //当前连接
  public $dbType = &#39;read&#39;;
  public $_host=&#39;&#39;; //数据库所在主机名
  public $_database = &#39;&#39;;//当前数据库名
  public $_tablename = &#39;&#39;;//当前表的表名
  public $_dt =&#39;&#39;;//database.tablename
  public $isRelease = 0; //查询完成后是否释放
  public $fields = &#39;*&#39;;
  public $arrWhere = [];
  public $order = &#39;&#39;;
  public $arrOrder = [];
  public $limit = &#39;&#39;;
  public $sql = &#39;&#39;;
  public $rs;//结果集
  private function __construct($database=&#39;&#39;, $tablename=&#39;&#39;, $isRelease=0)
  {
    $this->_database = $database;//database name
    $this->_tablename = $tablename;//table name
    $this->_dt = "`{$this->_database}`.`{$this->_tablename}`";
    $this->isRelease = $isRelease;
  }
  public static function getInstance($database=&#39;&#39;, $tablename=&#39;&#39;, $isRelease=0)
  {
    if (self::$Instance == null) {
      self::$Instance = new DBRWmysql($database, $tablename, $isRelease);
    }
    self::$Instance->_database = $database;
    self::$Instance->_tablename = $tablename;
    self::$Instance->_dt    = "`{$database}`.`{$tablename}`";
    self::$Instance->isRelease = $isRelease;
    return self::$Instance;
  }
  //如果主机没变,并且已经存在MYSQL连接,就不再创建新的连接
  //如果主机改变,就再生成一个实例创建一个连接
  //type == &#39;write&#39;或&#39;read&#39;
  public function getLink($type)
  {
    $this->dbType = $$type;
    //随机选取一个数据库连接(区分读写)
    $dbConfig = DBConfig::$$type;
    $randKey = array_rand($dbConfig);
    $config = $dbConfig[$randKey];
    //链接数据库
    $host = $config[&#39;host&#39;];
    $username = $config[&#39;username&#39;];
    $password = $config[&#39;password&#39;];
    if (empty($this->links[$host])) {
      $this->_host = $host;
      $this->links[$host] = new mysqli($host, $username, $password);
      if($this->links[$host]->connect_error) {
        $this->error($this->links[$host]->connect_error);
      }
    }
    //初始化链接
    $this->link = $this->links[$host];
    $this->link->query("set names utf8mb4;"); //支持emoji表情
    $this->link->query("use {$this->_database};");
  }
  public function getCurrentLinks()
  {
    return $this->links;
  }
  //析构函数
  public function __destruct()
  {
    foreach ($this->links as $v) {
      $v->close();
    }
  }
  //查询封装
  public function query($sql)
  {
    $this->sql = $sql;
    if (strpos($sql, &#39;select&#39;) !== false) {
      $this->getLink(&#39;read&#39;);//读库
    } else {
      $this->getLink(&#39;write&#39;);//写库
    }
    $this->rs = $this->link->query($sql);
    ($this->rs === false) && $this->error(&#39;sql error: &#39;.$sql.PHP_EOL.$this->link->error);
    //查询完成后释放链接, 并删除链接对象
    if ($this->isRelease) {
      $this->link->close();
      unset($this->links[$this->_host]);
    }
    return $this->rs;
  }
  //增
  public function insert($arrData)
  {
    foreach ($arrData as $key=>$value) {
      $fields[] = $key;
      $values[] = "&#39;".$value."&#39;";
      // $fields[] = &#39;`&#39;.$key.&#39;`&#39;;
      // $values[] = "&#39;".$value."&#39;";
    }
    $strFields = implode(&#39;,&#39;, $fields);
    $strValues = implode(&#39;,&#39;, $values);
    $sql = "insert into {$this->_dt} ($strFields) values ($strValues)";
    $this->query($sql);
    $insert_id = $this->link->insert_id;
    return $insert_id;
  }
  //增
  public function replace($arrData)
  {
    foreach ($arrData as $key=>$value) {
      $fields[] = $key;
      $values[] = "&#39;{$value}&#39;";
    }
    $strFields = implode(&#39;,&#39;, $fields);
    $strValues = implode(&#39;,&#39;, $values);
    $sql = "replace into {$this->_dt} ($strFields) values ($strValues)";
    $this->query($sql);
    return $this->link->insert_id;
  }
  //增
  //每次插入多条记录
  //每条记录的字段相同,但是值不一样
  public function insertm($arrFields, $arrData)
  {
    foreach ($arrFields as $v) {
      // $fields[] = "`{$v}`";
      $fields[] = $v;
    }
    foreach ($arrData as $v) {
      $data[] = &#39;(&#39;.implode(&#39;,&#39;, $v).&#39;)&#39;;
    }
    $strFields = implode(&#39;,&#39;, $fields);
    $strData = implode(&#39;,&#39;, $data);
    $sql = "insert into {$this->_dt} ($strFields) values {$strData}";
    $this->query($sql);
    return $this->link->insert_id;
  }
  //删
  public function delete()
  {
    $where = $this->getWhere();
    $limit = $this->getLimit();
    $sql = " delete from {$this->_dt} {$where} {$limit}";
    $this->query($sql);
    return $this->link->affected_rows;
  }
  //改
  public function update($data)
  {
    $where = $this->getWhere();
    $arrSql = array();
    foreach ($data as $key=>$value) {
      $arrSql[] = "{$key}=&#39;{$value}&#39;";
    }
    $strSql = implode(&#39;,&#39;, $arrSql);
    $sql = "update {$this->_dt} set {$strSql} {$where} {$this->limit}";
    $this->query($sql);
    return $this->link->affected_rows;
  }
  //获取总数
  public function getCount()
  {
    $where = $this->getWhere();
    $sql = " select count(1) as n from {$this->_dt} {$where} ";
    $resault = $this->query($sql);
    ($resault===false) && $this->error(&#39;getCount error: &#39;.$sql);
    $arrRs = $this->rsToArray($resault);
    $num = array_shift($arrRs);
    return $num[&#39;n&#39;];
  }
  //将结果集转换成数组返回
  //如果field不为空,则返回的数组以$field为键重新索引
  public function rsToArray($field = &#39;&#39;)
  {
    $arrRs = $this->rs->fetch_all(MYSQLI_ASSOC); //该函数只能用于php的mysqlnd驱动
    $this->rs->free();//释放结果集
    if ($field) {
      $arrResult = [];
      foreach ($arrRs as $v) {
        $arrResult[$v[$field]] = $v;
      }
      return $arrResult;
    }
    return $arrRs;
  }
  //给字段名加上反引号
  public function qw($strFields)
  {
    $strFields = preg_replace(&#39;#\s+#&#39;, &#39; &#39;, $strFields);
    $arrNewFields = explode(&#39; &#39;, $strFields );
    $arrNewFields = array_filter($arrNewFields);
    foreach ($arrNewFields as $k => $v) {

      $arrNewFields[$k]= &#39;`&#39;.$v.&#39;`&#39;;
    }
    return implode(&#39;,&#39;, $arrNewFields);
  }
  //处理入库数据,将字符串格式的数据转换为...格式(未实现)
  public function getInsertData($strData)
  {
    // $bmap = "jingdu,$jingdu weidu,$weidu content,$content";
  }
  //select in
  //arrData 整数数组,最好是整数
  public function select_in($key, $arrData, $fields=&#39;&#39;)
  {
    $fields = $fields ? $fields : &#39;*&#39;;
    sort($arrData);
    $len = count($arrData);
    $cur = 0;
    $pre = $arrData[0];
    $new = array(&#39;0&#39; => 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 ($new as $v) {
      $len = count($v) - 1;
      if ($len) {
        $s = $v[0];
        $e = end($v);
        $sql = "(select $fields from {$this->_dt} where $key between $s and $e)";
      } else {
        $s = $v[0];
        $sql = "(select $fields from {$this->_dt} where $key = $s)";
      }
      $arrSql[] = $sql;
    }
    $strUnion = implode(&#39; UNION ALL &#39;, $arrSql);
    $res = $this->query($strUnion);
    return $this->rstoarray($res);
  }
  //where in
  public function setWhereIn($key, $arrData)
  {
    if (empty($arrData)) {
      $str = "(`{$key}` in (&#39;0&#39;))";
      $this->addWhere($str);
      return $str;
    }
    foreach ($arrData as &$v) {
      $v = "&#39;{$v}&#39;";
    }
    $str = implode(&#39;,&#39;, $arrData);
    $str = "(`{$key}` in ( {$str} ))";
    $this->addWhere($str);
    return $this;
  }
  //where in
  public function setWhere($arrData)
  {
    if (empty($arrData)) {
      return &#39;&#39;;
    }
    foreach ($arrData as $k => $v) {
      $str = "(`{$k}` = &#39;{$v}&#39;)";
      $this->addWhere($str);
    }
    return $this;
  }
  //between and
  public function setWhereBetween($key, $min, $max)
  {
    $str = "(`{$key}` between &#39;{$min}&#39; and &#39;{$max}&#39;)";
    $this->addWhere($str);
    return $this;
  }
  //where a>b
  public function setWhereBT($key, $value)
  {
    $str = "(`{$key}` > &#39;{$value}&#39;)";
    $this->addWhere($str);
    return $this;
  }
  //where a<b
  public function setWhereLT($key, $value)
  {
    $str = "(`{$key}` < &#39;{$value}&#39;)";
    $this->addWhere($str);
    return $this;
  }
  //组装where条件
  public function addWhere($where)
  {
    $this->arrWhere[] = $where;
  }
  //获取最终查询用的where条件
  public function getWhere()
  {
    if (empty($this->arrWhere)) {
      return &#39;where 1&#39;;
    } else {
      return &#39;where &#39;.implode(&#39; and &#39;, $this->arrWhere);
    }
  }
  //以逗号隔开
  public function setFields($fields)
  {
    $this->fields = $fields;
    return $this;
  }
  // order by a desc
  public function setOrder($order)
  {
    $this->arrOrder[] = $order;
    return $this;
  }
  //获取order语句
  public function getOrder()
  {
    if (empty($this->arrOrder)) {
      return &#39;&#39;;
    } else {
      $str = implode(&#39;,&#39;, $this->arrOrder);
      $this->order = "order by {$str}";
    }
    return $this->order;
  }
  //e.g. &#39;0, 10&#39;
  //用limit的时候可以加where条件优化:select ... where id > 1234 limit 0, 10
  public function setLimit($limit)
  {
    $this->limit = &#39;limit &#39;.$limit;
    return $this;
  }
  //直接查询sql语句, 返回数组格式
  public function arrQuery($sql, $field=&#39;&#39;)
  {
    $this->query($sql);
    $this->clearQuery();
    ($this->rs===false) && $this->error(&#39;select error: &#39;.$sql);
    return $this->rsToArray($field);
  }
  //如果 $field 不为空, 则返回的结果以该字段的值为索引
  //暂不支持join
  public function get($field=&#39;&#39;)
  {
    $where = $this->getWhere();
    $order = $this->getOrder();
    $sql = " select {$this->fields} from {$this->_dt} {$where} {$order} {$this->limit} ";
    return $this->arrQuery($sql, $field);
  }
  //获取一条记录
  public function getOne()
  {
    $this->setLimit(1);
    $rs = $this->get();
    return !empty($rs) ? $rs[0] : [];
  }
  //获取一条记录的某一个字段的值
  public function getOneField($field)
  {
    $this->setFields($field);
    $rs = $this->getOne();
    return !empty($rs[$field]) ? $rs[$field] : &#39;&#39;;
  }
  //获取数据集中所有某个字段的值
  public function getFields($field)
  {
    $this->setFields($field);
    $rs = $this->get();
    $result = [];
    foreach ($rs as $v) {
      $result[] = $v[$field];
    }
    unset($rs);
    return $result;
  }
  //清除查询条件
  //防止干扰下次查询
  public function clearQuery()
  {
    $this->fields = &#39;*&#39;;
    $this->arrWhere = [];
    $this->order = &#39;&#39;;
    $this->arrOrder = [];
    $this->limit = &#39;&#39;;
  }
  //断开数据库连接
  public function close()
  {
    $this->link->close();
  }
  //事务
  //自动提交开关
  public function autocommit($bool)
  {
    $this->link->autocommit($bool);
  }
  //事务完成提交
  public function commit()
  {
    $this->link->commit();
  }
  //回滚
  public function rollback()
  {
    $this->link->rollback();
  }
  //输出错误sql语句
  public function error($sql)
  {
    //if (IS_TEST) {}
    exit($sql);
  }
}
登录后复制



总结:以上就是本篇文的全部内容,希望能对大家的学习有所帮助。

相关推荐:

PHP中try{}catch{}的使用方法

PHP自带方法验证邮箱、URL、IP是否合法的函数详解

PHP 根据key 给二维数组分组详解

以上是基于php实现带读写分离功能的MySQL类的详细内容。更多信息请关注PHP中文网其他相关文章!

相关标签:
来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责声明 Sitemap
PHP中文网:公益在线PHP培训,帮助PHP学习者快速成长!