开源CMS \ discuz \ 【discuzX2】/source/class/class_core.php文件中数据库操作类DB及db_mysql分析

【discuzX2】/source/class/class_core.php文件中数据库操作类DB及db_mysql分析

总点击60
简介:<?php /** *DiscuzMySQL类的支持程序中一般不直接使用此类,而是使用DB类,DB类对db_mysql类中的方法又进行了二次封装

<?php

/**

* Discuz MySQL 类的支持 程序中一般不直接使用此类,而是使用DB类,DB类对db_mysql类中的方法又进行了二次封装

*

*/

class db_mysql

{

var $tablepre;

var $version = '';

var $querynum = 0;

var $slaveid = 0;

var $curlink;

var $link = array();

var $config = array();

var $sqldebug = array();

var $map = array();

function db_mysql($config = array()) {

if(!empty($config)) {

$this->set_config($config);

}

}

function set_config($config) {

$this->config = &$config;

$this->tablepre = $config['1']['tablepre'];

if(!empty($this->config['map'])) {

$this->map = $this->config['map'];

}

}

function connect($serverid = 1) {

if(empty($this->config) || empty($this->config[$serverid])) {

$this->halt('config_db_not_found');

}

$this->link[$serverid] = $this->_dbconnect(

$this->config[$serverid]['dbhost'],

$this->config[$serverid]['dbuser'],

$this->config[$serverid]['dbpw'],

$this->config[$serverid]['dbcharset'],

$this->config[$serverid]['dbname'],

$this->config[$serverid]['pconnect']

);

$this->curlink = $this->link[$serverid];

}

function _dbconnect($dbhost,$dbuser,$dbpw,$dbcharset,$dbname,$pconnect) {

$link = null;

$func = empty($pconnect) ? 'mysql_connect' : 'mysql_pconnect';

if(!$link = @$func($dbhost,1)) {

$this->halt('notconnect');

} else {

$this->curlink = $link;

if($this->version() > '4.1') {

$dbcharset = $dbcharset ? $dbcharset : $this->config[1]['dbcharset'];

$serverset = $dbcharset ? 'character_set_connection='.$dbcharset.',character_set_results='.$dbcharset.',character_set_client=binary' : '';

$serverset .= $this->version() > '5.0.1' ? ((empty($serverset) ? '' : ',').'sql_mode=''') : '';

$serverset && mysql_query("SET $serverset",$link);

}

$dbname && @mysql_select_db($dbname,$link);

}

return $link;

}

function table_name($tablename) {

if(!empty($this->map) && !empty($this->map[$tablename])) {

$id = $this->map[$tablename];

if(!$this->link[$id]) {

$this->connect($id);

}

$this->curlink = $this->link[$id];

return $this->config[$id]['tablepre'].$tablename;

} else {

$this->curlink = $this->link[1];

}

return $this->tablepre.$tablename;

}

function select_db($dbname) {

return mysql_select_db($dbname,$this->curlink);

}

function fetch_array($query,$result_type = MYSQL_ASSOC) {

return mysql_fetch_array($query,$result_type);

}

function fetch_first($sql) {

return $this->fetch_array($this->query($sql));

}

function result_first($sql) {

return $this->result($this->query($sql),0);

}

function query($sql,$type = '') {

if(defined('DISCUZ_DEBUG') && DISCUZ_DEBUG) {

$starttime = dmicrotime();

}

$func = $type == 'UNBUFFERED' && @function_exists('mysql_unbuffered_query') ?

'mysql_unbuffered_query' : 'mysql_query';

if(!($query = $func($sql,$this->curlink))) {

if(in_array($this->errno(),array(2006,2013)) && substr($type,5) != 'RETRY') {

$this->connect();

return $this->query($sql,'RETRY'.$type);

}

if($type != 'SILENT' && substr($type,5) != 'SILENT') {

$this->halt('query_error',$sql);

}

}

if(defined('DISCUZ_DEBUG') && DISCUZ_DEBUG) {

$this->sqldebug[] = array($sql,number_format((dmicrotime() - $starttime),6),debug_backtrace());

}

$this->querynum++;

return $query;

}

function affected_rows() {

return mysql_affected_rows($this->curlink);

}

function error() {

return (($this->curlink) ? mysql_error($this->curlink) : mysql_error());

}

function errno() {

return intval(($this->curlink) ? mysql_errno($this->curlink) : mysql_errno());

}

function result($query,$row = 0) {

$query = @mysql_result($query,$row);

return $query;

}

function num_rows($query) {

$query = mysql_num_rows($query);

return $query;

}

function num_fields($query) {

return mysql_num_fields($query);

}

function free_result($query) {

return mysql_free_result($query);

}

function insert_id() {

return ($id = mysql_insert_id($this->curlink)) >= 0 ? $id : $this->result($this->query("SELECT last_insert_id()"),0);

}

function fetch_row($query) {

$query = mysql_fetch_row($query);

return $query;

}

function fetch_fields($query) {

return mysql_fetch_field($query);

}

function version() {

if(empty($this->version)) {

$this->version = mysql_get_server_info($this->curlink);

}

return $this->version;

}

function close() {

return mysql_close($this->curlink);

}

function halt($message = '',$sql = '') {

require_once libfile('class/error');

discuz_error::db_error($message,$sql);

}

}

/**

* 对Discuz CORE 中 DB Object中的主要方法进行二次封装,方便程序调用

*

*/

class DB

{

/**

* 返回表名(pre_$table)

*

* @param 原始表名 $table

* @return 增加pre之后的名字

*/

function table($table) {

return DB::_execute('table_name',$table);

}

/**

* 删除一条或者多条记录

*

* @param string $table 原始表名

* @param string $condition 条件语句,不需要写WHERE

* @param int $limit 删除条目数

* @param boolean $unbuffered 立即返回?

*/

function delete($table,$condition,$limit = 0,$unbuffered = true) {

if(empty($condition)) {

$where = '1';

} elseif(is_array($condition)) {

$where = DB::implode_field_value($condition,' AND ');

} else {

$where = $condition;

}

$sql = "DELETE FROM ".DB::table($table)." WHERE $where ".($limit ? "LIMIT $limit" : '');

return DB::query($sql,($unbuffered ? 'UNBUFFERED' : ''));

}

/**

* 插入一条记录

*

* @param string $table 原始表名

* @param array $data 数组field->vlaue 对

* @param boolen $return_insert_id 返回 InsertID?

* @param boolen $replace 是否是REPLACE模式

* @param boolen $silent 屏蔽错误?

* @return InsertID or Result

*/

function insert($table,$data,$return_insert_id = false,$replace = false,$silent = false) {

$sql = DB::implode_field_value($data);

$cmd = $replace ? 'REPLACE INTO' : 'INSERT INTO';

$table = DB::table($table);

$silent = $silent ? 'SILENT' : '';

$return = DB::query("$cmd $table SET $sql",$silent);

return $return_insert_id ? DB::insert_id() : $return;

}

/**

* 更新一条或者多条数据记录

*

* @param string $table 原始表名

* @param array $data 数据field-value

* @param string $condition 条件语句,不需要写WHERE

* @param boolean $unbuffered 迅速返回?

* @param boolan $low_priority 延迟更新?

* @return result

*/

function update($table,$unbuffered = false,$low_priority = false) {

$sql = DB::implode_field_value($data);

$cmd = "UPDATE ".($low_priority ? 'LOW_PRIORITY' : '');

$table = DB::table($table);

$where = '';

if(empty($condition)) {

$where = '1';

} elseif(is_array($condition)) {

$where = DB::implode_field_value($condition,' AND ');

} else {

$where = $condition;

}

$res = DB::query("$cmd $table SET $sql WHERE $where",$unbuffered ? 'UNBUFFERED' : '');

return $res;

}

/**

* 格式化field字段和value,并组成一个字符串

*

* @param array $array 格式为 key=>value 数组

* @param 分割符 $glue

* @return string

*/

function implode_field_value($array,$glue = ',') {

$sql = $comma = '';

foreach ($array as $k => $v) {

$sql .= $comma."`$k`='$v'";

$comma = $glue;

}

return $sql;

}

/**

* 返回插入的ID

*

* @return int

*/

function insert_id() {

return DB::_execute('insert_id');

}

/**

* 依据查询结果,返回一行数据

*

* @param resourceID $resourceid

* @return array

*/

function fetch($resourceid,$type = MYSQL_ASSOC) {

return DB::_execute('fetch_array',$resourceid,$type);

}

/**

* 依据SQL语句,返回第一条查询结果

*

* @param string $query 查询语句

* @return array

*/

function fetch_first($sql) {

DB::checkquery($sql);

return DB::_execute('fetch_first',$sql);

}

/**

* 依据查询结果,返回结果数值

*

* @param resourceid $resourceid

* @return string or int

*/

function result($resourceid,$row = 0) {

return DB::_execute('result',$row);

}

/**

* 依据查询语句,返回结果数值

*

* @param string $query SQL查询语句

* @return unknown

*/

function result_first($sql) {

DB::checkquery($sql);

return DB::_execute('result_first',$sql);

}

/**

* 执行查询

*

* @param string $sql

* @param 类型定义 $type UNBUFFERED OR SILENT

* @return Resource OR Result

*/

function query($sql,$type = '') {

DB::checkquery($sql);

return DB::_execute('query',$sql,$type);

}

/**

* 返回select的结果行数

*

* @param resource $resourceid

* @return int

*/

function num_rows($resourceid) {

return DB::_execute('num_rows',$resourceid);

}

/**

* 返回sql语句所影响的记录行数

*

* @return int

*/

function affected_rows() {

return DB::_execute('affected_rows');

}

function free_result($query) {

return DB::_execute('free_result',$query);

}

function error() {

return DB::_execute('error');

}

function errno() {

return DB::_execute('errno');

}

function _execute($cmd,$arg1 = '',$arg2 = '') {//DB类中的很多方法都调用了此方法,此方法又调用了 &object()方法,详情请查看&object()方法,其实&object()方法返回一个db_mysql类的实例化对象,而且是statics类型的实例化对象

static $db;

if(empty($db)) $db = & DB::object();//返回db_mysql操作类的实例化对象

$res = $db->$cmd($arg1,$arg2);

return $res;

}

/**

* 返回 DB object 指针

*

* @return pointer of db object from discuz core

*/

function &object($dbclass = 'db_mysql') {

static $db;

if(empty($db)) $db = new $dbclass();//返回db_mysql数据库操作类的一个statics类型的实例化对象

return $db;

}

function checkquery($sql) {

static $status = null,$checkcmd = array('SELECT','UPDATE','INSERT','REPLACE','DELETE');

if($status === null) $status = getglobal('config/security/querysafe/status');

if($status) {

$cmd = trim(strtoupper(substr($sql,strpos($sql,' '))));

if(in_array($cmd,$checkcmd)) {

$test = DB::_do_query_safe($sql);

if($test < 1) DB::_execute('halt','security_error',$sql);

}

}

return true;

}

function _do_query_safe($sql) {

static $_CONFIG = null;

if($_CONFIG === null) {

$_CONFIG = getglobal('config/security/querysafe');

}

$sql = str_replace(array('\',''','"',''''),'',$sql);

$mark = $clean = '';

if(strpos($sql,'/') === false && strpos($sql,'#') === false && strpos($sql,'-- ') === false) {

$clean = preg_replace("/'(.+?)'/s",$sql);

} else {

$len = strlen($sql);

$mark = $clean = '';

for ($i = 0; $i <$len; $i++) {

$str = $sql[$i];

switch ($str) {

case ''':

if(!$mark) {

$mark = ''';

$clean .= $str;

} elseif ($mark == ''') {

$mark = '';

}

break;

case '/':

if(empty($mark) && $sql[$i+1] == '*') {

$mark = '/*';

$clean .= $mark;

$i++;

} elseif($mark == '/*' && $sql[$i -1] == '*') {

$mark = '';

$clean .= '*';

}

break;

case '#':

if(empty($mark)) {

$mark = $str;

$clean .= $str;

}

break;

case "n":

if($mark == '#' || $mark == '--') {

$mark = '';

}

break;

case '-':

if(empty($mark)&& substr($sql,$i,3) == '-- ') {

$mark = '-- ';

$clean .= $mark;

}

break;

default:

break;

}

$clean .= $mark ? '' : $str;

}

}

$clean = preg_replace("/[^a-z0-9_-()#*/"]+/is","",strtolower($clean));

if($_CONFIG['afullnote']) {

$clean = str_replace('/**/',$clean);

}

if(is_array($_CONFIG['dfunction'])) {

foreach($_CONFIG['dfunction'] as $fun) {

if(strpos($clean,$fun.'(') !== false) return '-1';

}

}

if(is_array($_CONFIG['daction'])) {

foreach($_CONFIG['daction'] as $action) {

if(strpos($clean,$action) !== false) return '-3';

}

}

if($_CONFIG['dlikehex'] && strpos($clean,'like0x')) {

return '-2';

}

if(is_array($_CONFIG['dnote'])) {

foreach($_CONFIG['dnote'] as $note) {

if(strpos($clean,$note) !== false) return '-4';

}

}

return 1;

}

}

?>


意见反馈 常见问题 官方微信 返回顶部