<?php
class cpMysqli {
private $_writeLink = NULL; //主
private $_readLink = NULL; //從
private $_replication = false; //標誌是否支持主從
private $dbConfig = array();
public $sql = "";
public function __construct($dbConfig = array()){
$this->dbConfig = $dbConfig;
//判斷是否支持主從
$this->_replication = isset($this->dbConfig['DB_SLAVE']) && !empty($this->dbConfig['DB_SLAVE']);
}
//執行sql查詢
public function query($sql, $params = array()) {
foreach($params as $k => $v){
$sql = str_replace(':'.$k, $this->escape($v), $sql);
}
$this->sql = $sql;
if( $query = $this->_getReadLink()->query($sql) )
return $query;
else
$this->error('MySQL Query Error', $this->_getReadLink()->error, $this->_getReadLink()->errno);
}
//執行sql命令
public function execute($sql, $params = array()) {
foreach($params as $k => $v){
$sql = str_replace(':'.$k, $this->escape($v), $sql);
}
$this->sql = $sql;
if( $query = $this->_getWriteLink()->query($sql) )
return $query;
else
$this->error('MySQL Query Error', $this->_getWriteLink()->error, $this->_getWriteLink()->errno);
}
//從結果集中取得一行作爲關聯數組,或數字數組,或二者兼有
public function fetchArray($query, $result_type = MYSQLI_ASSOC) {
return $this->unEscape( $query->fetch_array($result_type) );
}
//取得前一次 MySQL 操作所影響的記錄行數
public function affectedRows() {
return $this->_getWriteLink()->affected_rows;
}
//獲取上一次插入的id
public function lastId() {
return $this->_getWriteLink()->insert_id;
}
//獲取表結構
public function getFields($table) {
$this->sql = "SHOW FULL FIELDS FROM {$table}";
$query = $this->query($this->sql);
$data = array();
while($row = $this->fetchArray($query)){
$data[] = $row;
}
return $data;
}
//獲取行數
public function count($table,$where) {
$this->sql = "SELECT count(*) FROM $table $where";
$query = $this->query($this->sql);
$data = $this->fetchArray($query);
return $data['count(*)'];
}
//數據過濾
public function escape($value) {
if( isset($this->_readLink) ) {
$mysqli = $this->_readLink;
} elseif( isset($this->_writeLink) ) {
$mysqli = $this->_writeLink;
} else {
$mysqli = $this->_getReadLink();
}
if( is_array($value) ) {
return array_map(array($this, 'escape'), $value);
} else {
if( get_magic_quotes_gpc() ) {
$value = stripslashes($value);
}
return "'" . $mysqli->real_escape_string($value) . "'";
}
}
//數據過濾
public function unEscape($value) {
if (is_array($value)) {
return array_map('stripslashes', $value);
} else {
return stripslashes($value);
}
}
//解析待添加或修改的數據
public function parseData($options, $type) {
//如果數據是字符串,直接返回
if(is_string($options['data'])) {
return $options['data'];
}
if( is_array($options) && !empty($options) ) {
switch($type){
case 'add':
$data = array();
$data['fields'] = array_keys($options['data']);
$data['values'] = $this->escape( array_values($options['data']) );
return " (`" . implode("`,`", $data['fields']) . "`) VALUES (" . implode(",", $data['values']) . ") ";
case 'save':
$data = array();
foreach($options['data'] as $key => $value) {
$data[] = " `$key` = " . $this->escape($value);
}
return implode(',', $data);
default:return false;
}
}
return false;
}
//解析查詢條件
public function parseCondition($options) {
$condition = "";
if(!empty($options['where'])) {
$condition = " WHERE ";
if(is_string($options['where'])) {
$condition .= $options['where'];
} else if(is_array($options['where'])) {
foreach($options['where'] as $key => $value) {
$condition .= " `$key` = " . $this->escape($value) . " AND ";
}
$condition = substr($condition, 0,-4);
} else {
$condition = "";
}
}
if( !empty($options['group']) && is_string($options['group']) ) {
$condition .= " GROUP BY " . $options['group'];
}
if( !empty($options['having']) && is_string($options['having']) ) {
$condition .= " HAVING " . $options['having'];
}
if( !empty($options['order']) && is_string($options['order']) ) {
$condition .= " ORDER BY " . $options['order'];
}
if( !empty($options['limit']) && (is_string($options['limit']) || is_numeric($options['limit'])) ) {
$condition .= " LIMIT " . $options['limit'];
}
if( empty($condition) ) return "";
return $condition;
}
//輸出錯誤信息
public function error($message = '',$error = '', $errorno = ''){
if( DEBUG ){
$str = " {$message}<br>
<b>SQL</b>: {$this->sql}<br>
<b>錯誤詳情</b>: {$error}<br>
<b>錯誤代碼</b>:{$errorno}<br>";
} else {
$str = "<b>出錯</b>: $message<br>";
}
throw new Exception($str);
}
//獲取從服務器連接
private function _getReadLink() {
if( isset( $this->_readLink ) ) {
$this->_readLink->ping();
return $this->_readLink;
} else {
if( !$this->_replication ) {
return $this->_getWriteLink();
} else {
$this->_readLink = $this->_connect( false );
return $this->_readLink;
}
}
}
//獲取主服務器連接
private function _getWriteLink() {
if( isset( $this->_writeLink ) ) {
$this->_writeLink->ping();
return $this->_writeLink;
} else{
$this->_writeLink = $this->_connect( true );
return $this->_writeLink;
}
}
//數據庫鏈接
private function _connect($is_master = true) {
if( ($is_master == false) && $this->_replication ) {
$slave_count = count($this->dbConfig['DB_SLAVE']);
//遍歷所有從機
for($i = 0; $i < $slave_count; $i++) {
$db_all[] = array_merge($this->dbConfig, $this->dbConfig['DB_SLAVE'][$i]);
}
$db_all[] = $this->dbConfig;//如果所有從機都連接不上,連接到主機
//隨機選擇一臺從機連接
$rand = mt_rand(0, $slave_count-1);
$db = array_unshift($db_all, $db_all[$rand]);
} else {
$db_all[] = $this->dbConfig; //直接連接到主機
}
foreach($db_all as $db) {
$mysqli = @new mysqli($db['DB_HOST'], $db['DB_USER'], $db['DB_PWD'], $db['DB_NAME'], $db['DB_PORT']);
if($mysqli->connect_errno == 0 ) {
break;
}
}
if($mysqli->connect_errno){
$this->error('無法連接到數據庫服務器', $mysqli->connect_error, $mysqli->connect_errno);
}
//設置編碼
$mysqli->query("SET NAMES {$db['DB_CHARSET']}");
return $mysqli;
}
//關閉數據庫
public function __destruct() {
if($this->_writeLink) {
$this->_writeLink->close();
}
if($this->_readLink) {
$this->_readLink->close();
}
}
}
<?php
class cpMysql {
private $_writeLink = NULL; //主
private $_readLink = NULL; //從
private $_replication = false; //標誌是否支持主從
private $dbConfig = array();
public $sql = "";
public function __construct( $dbConfig = array() ){
$this->dbConfig = $dbConfig;
//判斷是否支持主從
$this->_replication = isset( $this->dbConfig['DB_SLAVE']) && !empty($this->dbConfig['DB_SLAVE'] );
}
//執行sql查詢
public function query($sql, $params = array()) {
foreach($params as $k => $v){
$sql = str_replace(':'.$k, $this->escape($v), $sql);
}
$this->sql = $sql;
if( $query = mysql_query($sql, $this->_getReadLink()) )
return $query;
else
$this->error('MySQL Query Error');
}
//執行sql命令
public function execute($sql, $params = array()) {
foreach($params as $k => $v){
$sql = str_replace(':'.$k, $this->escape($v), $sql);
}
$this->sql = $sql;
if( $query = mysql_query($sql, $this->_getWriteLink()) )
return $query;
else
$this->error('MySQL Query Error');
}
//從結果集中取得一行作爲關聯數組,或數字數組,或二者兼有
public function fetchArray($query, $result_type = MYSQL_ASSOC) {
return $this->unEscape( mysql_fetch_array($query, $result_type) );
}
//取得前一次 MySQL 操作所影響的記錄行數
public function affectedRows() {
return mysql_affected_rows($this->_getWriteLink());
}
//獲取上一次插入的id
public function lastId() {
return ($id = mysql_insert_id( $this->_getWriteLink() )) >= 0 ? $id : mysql_result($this->execute("SELECT last_insert_id()"), 0);
}
//獲取表結構
public function getFields($table) {
$this->sql = "SHOW FULL FIELDS FROM {$table}";
$query = $this->query($this->sql);
$data = array();
while($row = $this->fetchArray($query)){
$data[] = $row;
}
return $data;
}
//獲取行數
public function count($table,$where) {
$this->sql = "SELECT count(*) FROM $table $where";
$query = $this->query($this->sql);
$data = $this->fetchArray($query);
return $data['count(*)'];
}
//數據過濾
public function escape($value) {
if( isset($this->_readLink) ) {
$link = $this->_readLink;
} elseif( isset($this->_writeLink) ) {
$link = $this->_writeLink;
} else {
$link = $this->_getReadLink();
}
if( is_array($value) ) {
return array_map(array($this, 'escape'), $value);
} else {
if( get_magic_quotes_gpc() ) {
$value = stripslashes($value);
}
return "'" . mysql_real_escape_string($value, $link) . "'";
}
}
//數據過濾
public function unEscape($value) {
if (is_array($value)) {
return array_map('stripslashes', $value);
} else {
return stripslashes($value);
}
}
//解析待添加或修改的數據
public function parseData($options, $type) {
//如果數據是字符串,直接返回
if(is_string($options['data'])) {
return $options['data'];
}
if( is_array($options) && !empty($options) ) {
switch($type){
case 'add':
$data = array();
$data['fields'] = array_keys($options['data']);
$data['values'] = $this->escape( array_values($options['data']) );
return " (`" . implode("`,`", $data['fields']) . "`) VALUES (" . implode(",", $data['values']) . ") ";
case 'save':
$data = array();
foreach($options['data'] as $key => $value) {
$data[] = " `$key` = " . $this->escape($value);
}
return implode(',', $data);
default:return false;
}
}
return false;
}
//解析查詢條件
public function parseCondition($options) {
$condition = "";
if(!empty($options['where'])) {
$condition = " WHERE ";
if(is_string($options['where'])) {
$condition .= $options['where'];
} else if(is_array($options['where'])) {
foreach($options['where'] as $key => $value) {
$condition .= " `$key` = " . $this->escape($value) . " AND ";
}
$condition = substr($condition, 0,-4);
} else {
$condition = "";
}
}
if( !empty($options['group']) && is_string($options['group']) ) {
$condition .= " GROUP BY " . $options['group'];
}
if( !empty($options['having']) && is_string($options['having']) ) {
$condition .= " HAVING " . $options['having'];
}
if( !empty($options['order']) && is_string($options['order']) ) {
$condition .= " ORDER BY " . $options['order'];
}
if( !empty($options['limit']) && (is_string($options['limit']) || is_numeric($options['limit'])) ) {
$condition .= " LIMIT " . $options['limit'];
}
if( empty($condition) ) return "";
return $condition;
}
//輸出錯誤信息
public function error($message = ''){
$error = mysql_error();
$errorno = mysql_errno();
if( DEBUG ){
$str = " {$message}<br>
<b>SQL</b>: {$this->sql}<br>
<b>錯誤詳情</b>: {$error}<br>
<b>錯誤代碼</b>:{$errorno}<br>";
} else {
$str = "<b>出錯</b>: $message<br>";
}
throw new Exception($str);
}
/******************兼容以前的版本*****************************/
//選擇數據庫
public function select_db($dbname) {
return mysql_select_db($dbname, $this->_getWriteLink());
}
//從結果集中取得一行作爲關聯數組,或數字數組,或二者兼有
public function fetch_array($query, $result_type = MYSQL_ASSOC) {
return $this->fetchArray($query, $result_type);
}
//獲取上一次插入的id
public function insert_id() {
return $this->lastId();
}
//取得前一次 MySQL 操作所影響的記錄行數
public function affected_rows() {
return $this->affectedRows();
}
//取得結果集中行的數目
public function num_rows($query) {
return mysql_num_rows($query);
}
/******************兼容以前的版本*****************************/
//獲取從服務器連接
private function _getReadLink() {
if( isset( $this->_readLink ) ) {
mysql_ping( $this->_readLink );
return $this->_readLink;
} else {
if( !$this->_replication ) {
return $this->_getWriteLink();
} else {
$this->_readLink = $this->_connect( false );
return $this->_readLink;
}
}
}
//獲取主服務器連接
private function _getWriteLink() {
if( isset( $this->_writeLink ) ) {
mysql_ping( $this->_writeLink );
return $this->_writeLink;
} else{
$this->_writeLink = $this->_connect( true );
return $this->_writeLink;
}
}
//數據庫鏈接
private function _connect($is_master = true) {
if( ($is_master == false) && $this->_replication ) {
$slave_count = count($this->dbConfig['DB_SLAVE']);
//遍歷所有從機
for($i = 0; $i < $slave_count; $i++) {
$db_all[] = array_merge($this->dbConfig, $this->dbConfig['DB_SLAVE'][$i]);
}
$db_all[] = $this->dbConfig;//如果所有從機都連接不上,連接到主機
//隨機選擇一臺從機連接
$rand = mt_rand(0, $slave_count-1);
$db = array_unshift($db_all, $db_all[$rand]);
} else {
$db_all[] = $this->dbConfig; //直接連接到主機
}
foreach($db_all as $db) {
if( $link = @mysql_connect($db['DB_HOST'] . ':' . $db['DB_PORT'], $db['DB_USER'], $db['DB_PWD'])) {
break;
}
}
if(!$link){
$this->error('無法連接到數據庫服務器');
}
$version = mysql_get_server_info($link);
if($version > '4.1') {
mysql_query("SET character_set_connection = " . $db['DB_CHARSET'] . ", character_set_results = " . $db['DB_CHARSET'] . ", character_set_client = binary", $link);
if($version > '5.0.1') {
mysql_query("SET sql_mode = ''", $link);
}
}
mysql_select_db($db['DB_NAME'], $link);
return $link;
}
//關閉數據庫
public function __destruct() {
if($this->_writeLink) {
@mysql_close($this->_writeLink);
}
if($this->_readLink) {
@mysql_close($this->_readLink);
}
}
}