读写分离MYSQL类
2014年4月27日 12:34:08
概述:
1. 根据sql语句判断是连接读库还是写库
2. 链式调用$this->where()->get()
3. 不同的主机对应不同的实例, 不再多次new
1 <?php 2 class DBRWmysql 3 { 4 private static $Instance = null; 5 6 private $links = array();//链接数组 7 private $link = null; //当前连接 8 public $dbType = 'read'; 9 10 public $_host=''; //数据库所在主机名 11 public $_database = '';//当前数据库名 12 public $_tablename = '';//当前表的表名 13 public $_dt ='';//database.tablename 14 public $isRelease = 0; //查询完成后是否释放 15 16 public $fields = '*'; 17 public $arrWhere = []; 18 public $order = ''; 19 public $arrOrder = []; 20 public $limit = ''; 21 public $sql = ''; 22 23 public $rs;//结果集 24 25 private function __construct($database='', $tablename='', $isRelease=0) 26 { 27 $this->_database = $database;//database name 28 $this->_tablename = $tablename;//table name 29 $this->_dt = "`{$this->_database}`.`{$this->_tablename}`"; 30 $this->isRelease = $isRelease; 31 } 32 33 public static function getInstance($database='', $tablename='', $isRelease=0) 34 { 35 if (self::$Instance == null) { 36 self::$Instance = new DBRWmysql($database, $tablename, $isRelease); 37 } 38 39 self::$Instance->_database = $database; 40 self::$Instance->_tablename = $tablename; 41 self::$Instance->_dt = "`{$database}`.`{$tablename}`"; 42 self::$Instance->isRelease = $isRelease; 43 44 return self::$Instance; 45 } 46 47 //如果主机没变,并且已经存在MYSQL连接,就不再创建新的连接 48 //如果主机改变,就再生成一个实例创建一个连接 49 //type == 'write'或'read' 50 public function getLink($type) 51 { 52 $this->dbType = $$type; 53 54 //随机选取一个数据库连接(区分读写) 55 $dbConfig = DBConfig::$$type; 56 $randKey = array_rand($dbConfig); 57 $config = $dbConfig[$randKey]; 58 59 //链接数据库 60 $host = $config['host']; 61 $username = $config['username']; 62 $password = $config['password']; 63 64 if (empty($this->links[$host])) { 65 $this->_host = $host; 66 $this->links[$host] = new mysqli($host, $username, $password); 67 if($this->links[$host]->connect_error) { 68 $this->error($this->links[$host]->connect_error); 69 } 70 } 71 72 //初始化链接 73 $this->link = $this->links[$host]; 74 $this->link->query("set names utf8mb4;"); //支持emoji表情 75 $this->link->query("use {$this->_database};"); 76 } 77 78 public function getCurrentLinks() 79 { 80 return $this->links; 81 } 82 83 //析构函数 84 public function __destruct() 85 { 86 foreach ($this->links as $v) { 87 $v->close(); 88 } 89 } 90 91 //查询封装 92 public function query($sql) 93 { 94 $this->sql = $sql; 95 if (strpos($sql, 'select') !== false) { 96 $this->getLink('read');//读库 97 } else { 98 $this->getLink('write');//写库 99 } 100 101 $this->rs = $this->link->query($sql); 102 ($this->rs === false) && $this->error('sql error: '.$sql.PHP_EOL.$this->link->error); 103 104 //查询完成后释放链接, 并删除链接对象 105 if ($this->isRelease) { 106 $this->link->close(); 107 unset($this->links[$this->_host]); 108 } 109 return $this->rs; 110 } 111 112 113 //增 114 public function insert($arrData) 115 { 116 foreach ($arrData as $key=>$value) { 117 $fields[] = $key; 118 $values[] = "'".$value."'"; 119 // $fields[] = '`'.$key.'`'; 120 // $values[] = "'".$value."'"; 121 } 122 $strFields = implode(',', $fields); 123 $strValues = implode(',', $values); 124 $sql = "insert into {$this->_dt} ($strFields) values ($strValues)"; 125 $this->query($sql); 126 $insert_id = $this->link->insert_id; 127 128 return $insert_id; 129 } 130 131 //增 132 public function replace($arrData) 133 { 134 foreach ($arrData as $key=>$value) { 135 $fields[] = $key; 136 $values[] = "'{$value}'"; 137 } 138 $strFields = implode(',', $fields); 139 $strValues = implode(',', $values); 140 $sql = "replace into {$this->_dt} ($strFields) values ($strValues)"; 141 142 $this->query($sql); 143 144 return $this->link->insert_id; 145 } 146 147 //增 148 //每次插入多条记录 149 //每条记录的字段相同,但是值不一样 150 public function insertm($arrFields, $arrData) 151 { 152 foreach ($arrFields as $v) { 153 // $fields[] = "`{$v}`"; 154 $fields[] = $v; 155 } 156 157 foreach ($arrData as $v) { 158 $data[] = '('.implode(',', $v).')'; 159 } 160 161 $strFields = implode(',', $fields); 162 $strData = implode(',', $data); 163 164 $sql = "insert into {$this->_dt} ($strFields) values {$strData}"; 165 166 $this->query($sql); 167 168 return $this->link->insert_id; 169 } 170 171 //删 172 public function delete() 173 { 174 $where = $this->getWhere(); 175 $limit = $this->getLimit(); 176 177 $sql = " delete from {$this->_dt} {$where} {$limit}"; 178 $this->query($sql); 179 return $this->link->affected_rows; 180 } 181 182 //改 183 public function update($data) 184 { 185 $where = $this->getWhere(); 186 187 $arrSql = array(); 188 foreach ($data as $key=>$value) { 189 $arrSql[] = "{$key}='{$value}'"; 190 } 191 $strSql = implode(',', $arrSql); 192 193 $sql = "update {$this->_dt} set {$strSql} {$where} {$this->limit}"; 194 195 $this->query($sql); 196 197 return $this->link->affected_rows; 198 199 } 200 201 //获取总数 202 public function getCount() 203 { 204 $where = $this->getWhere(); 205 206 $sql = " select count(1) as n from {$this->_dt} {$where} "; 207 $resault = $this->query($sql); 208 209 ($resault===false) && $this->error('getCount error: '.$sql); 210 211 $arrRs = $this->rsToArray($resault); 212 213 $num = array_shift($arrRs); 214 return $num['n']; 215 } 216 217 //将结果集转换成数组返回 218 //如果field不为空,则返回的数组以$field为键重新索引 219 public function rsToArray($field = '') 220 { 221 $arrRs = $this->rs->fetch_all(MYSQLI_ASSOC); //该函数只能用于php的mysqlnd驱动 222 $this->rs->free();//释放结果集 223 224 if ($field) { 225 $arrResult = []; 226 foreach ($arrRs as $v) { 227 $arrResult[$v[$field]] = $v; 228 } 229 return $arrResult; 230 } 231 232 return $arrRs; 233 } 234 235 //给字段名加上反引号 236 public function qw($strFields) 237 { 238 $strFields = preg_replace('#\s+#', ' ', $strFields); 239 $arrNewFields = explode(' ', $strFields ); 240 $arrNewFields = array_filter($arrNewFields); 241 foreach ($arrNewFields as $k => $v) { 242 $arrNewFields[$k]= '`'.$v.'`'; 243 } 244 return implode(',', $arrNewFields); 245 } 246 247 //处理入库数据,将字符串格式的数据转换为...格式(未实现) 248 public function getInsertData($strData) 249 { 250 // $bmap = "jingdu,$jingdu weidu,$weidu content,$content"; 251 } 252 253 //select in 254 //arrData 整数数组,最好是整数 255 public function select_in($key, $arrData, $fields='') 256 { 257 $fields = $fields ? $fields : '*'; 258 sort($arrData); 259 $len = count($arrData); 260 $cur = 0; 261 $pre = $arrData[0]; 262 263 $new = array('0' => array($arrData[0])); 264 for ($i = 1; $i < $len; $i++) { 265 if (($arrData[$i] - $pre) == 1 ) { 266 $new[$cur][] = $arrData[$i]; 267 } else { 268 $cur = $i; 269 $new[$cur][] = $arrData[$i]; 270 } 271 $pre = $arrData[$i]; 272 } 273 274 $arrSql = array(); 275 foreach ($new as $v) { 276 $len = count($v) - 1; 277 if ($len) { 278 $s = $v[0]; 279 $e = end($v); 280 $sql = "(select $fields from {$this->_dt} where $key between $s and $e)"; 281 } else { 282 $s = $v[0]; 283 $sql = "(select $fields from {$this->_dt} where $key = $s)"; 284 } 285 286 $arrSql[] = $sql; 287 } 288 289 $strUnion = implode(' UNION ALL ', $arrSql); 290 $res = $this->query($strUnion); 291 return $this->rstoarray($res); 292 } 293 294 //where in 295 public function setWhereIn($key, $arrData) 296 { 297 if (empty($arrData)) { 298 $str = "(`{$key}` in ('0'))"; 299 $this->addWhere($str); 300 return $str; 301 } 302 303 foreach ($arrData as &$v) { 304 $v = "'{$v}'"; 305 } 306 $str = implode(',', $arrData); 307 $str = "(`{$key}` in ( {$str} ))"; 308 309 $this->addWhere($str); 310 311 return $this; 312 } 313 314 //where in 315 public function setWhere($arrData) 316 { 317 if (empty($arrData)) { 318 return ''; 319 } 320 321 foreach ($arrData as $k => $v) { 322 $str = "(`{$k}` = '{$v}')"; 323 $this->addWhere($str); 324 } 325 326 return $this; 327 } 328 329 //between and 330 public function setWhereBetween($key, $min, $max) 331 { 332 $str = "(`{$key}` between '{$min}' and '{$max}')"; 333 $this->addWhere($str); 334 return $this; 335 } 336 337 //where a>b 338 public function setWhereBT($key, $value) 339 { 340 $str = "(`{$key}` > '{$value}')"; 341 $this->addWhere($str); 342 return $this; 343 } 344 345 //where a<b 346 public function setWhereLT($key, $value) 347 { 348 $str = "(`{$key}` < '{$value}')"; 349 $this->addWhere($str); 350 return $this; 351 } 352 353 //组装where条件 354 public function addWhere($where) 355 { 356 $this->arrWhere[] = $where; 357 } 358 359 //获取最终查询用的where条件 360 public function getWhere() 361 { 362 if (empty($this->arrWhere)) { 363 return 'where 1'; 364 } else { 365 return 'where '.implode(' and ', $this->arrWhere); 366 } 367 } 368 369 //以逗号隔开 370 public function setFields($fields) 371 { 372 $this->fields = $fields; 373 return $this; 374 } 375 376 // order by a desc 377 public function setOrder($order) 378 { 379 $this->arrOrder[] = $order; 380 return $this; 381 } 382 383 //获取order语句 384 public function getOrder() 385 { 386 if (empty($this->arrOrder)) { 387 return ''; 388 } else { 389 $str = implode(',', $this->arrOrder); 390 $this->order = "order by {$str}"; 391 } 392 return $this->order; 393 } 394 395 //e.g. '0, 10' 396 //用limit的时候可以加where条件优化:select ... where id > 1234 limit 0, 10 397 public function setLimit($limit) 398 { 399 $this->limit = 'limit '.$limit; 400 return $this; 401 } 402 403 //直接查询sql语句, 返回数组格式 404 public function arrQuery($sql, $field='') 405 { 406 $this->query($sql); 407 $this->clearQuery(); 408 ($this->rs===false) && $this->error('select error: '.$sql); 409 return $this->rsToArray($field); 410 } 411 412 //如果 $field 不为空, 则返回的结果以该字段的值为索引 413 //暂不支持join 414 public function get($field='') 415 { 416 $where = $this->getWhere(); 417 $order = $this->getOrder(); 418 419 $sql = " select {$this->fields} from {$this->_dt} {$where} {$order} {$this->limit} "; 420 return $this->arrQuery($sql, $field); 421 } 422 423 //获取一条记录 424 public function getOne() 425 { 426 $this->setLimit(1); 427 $rs = $this->get(); 428 429 return !empty($rs) ? $rs[0] : []; 430 } 431 432 //获取一条记录的某一个字段的值 433 public function getOneField($field) 434 { 435 $this->setFields($field); 436 $rs = $this->getOne(); 437 438 return !empty($rs[$field]) ? $rs[$field] : ''; 439 } 440 441 //获取数据集中所有某个字段的值 442 public function getFields($field) 443 { 444 $this->setFields($field); 445 $rs = $this->get(); 446 $result = []; 447 foreach ($rs as $v) { 448 $result[] = $v[$field]; 449 } 450 unset($rs); 451 452 return $result; 453 } 454 455 //清除查询条件 456 //防止干扰下次查询 457 public function clearQuery() 458 { 459 $this->fields = '*'; 460 $this->arrWhere = []; 461 $this->order = ''; 462 $this->arrOrder = []; 463 $this->limit = ''; 464 } 465 466 //断开数据库连接 467 public function close() 468 { 469 $this->link->close(); 470 } 471 472 //事务 473 //自动提交开关 474 public function autocommit($bool) 475 { 476 $this->link->autocommit($bool); 477 } 478 479 //事务完成提交 480 public function commit() 481 { 482 $this->link->commit(); 483 } 484 485 //回滚 486 public function rollback() 487 { 488 $this->link->rollback(); 489 } 490 491 492 //输出错误sql语句 493 public function error($sql) 494 { 495 //if (IS_TEST) {} 496 exit($sql); 497 } 498 }
最后编辑: 2016年4月16日 19:45:14 星期六