1. 类文件位置 Core/lib/mysql.php
数据库交互操作
~~~
<?php
/**
* 数据库直接交互操作封装
*/
class ms_mysql
{
var $dns = '';
var $query_num = 0;
var $link = '';
var $catch = FALSE;
var $sqls = '';
function __construct(& $dns)
{
$this->dns = $dns;
if(DEBUG) $this->sqls = array();
}
function connect()
{
if($this->link && mysql_ping($this->link)) {
return;
}
if(DEBUG) {
$mtime = explode(' ', microtime());
$starttime = $mtime[1] + $mtime[0];
$this->sqls[] = 'Connect MySQL';
}
$func = $this->dns['pconnect'] ? "mysql_pconnect" : "mysql_connect";
if(!$this->link = @$func($this->dns['dbhost'], $this->dns['dbuser'], $this->dns['dbpw'], 1)) {
$this->_halt("Can not connect to MySQL server");
}
if(version_compare($this->version(),'5.0.1','>=')) {
mysql_query("SET sql_mode=''", $this->link);
}
if(version_compare($this->version(),'5.0.6','>')) {
mysql_set_charset($this->dns['dbcharset'], $this->link);
} else {
mysql_query("SET NAMES '" . $this->dns['dbcharset'] . "'", $this->link);
}
if($this->dns['dbname']) {
if (!@mysql_select_db($this->dns['dbname'], $this->link)) {
$this->_halt('Cannot use database '.$this->dns['dbname']);
}
}
if(DEBUG) {
$mtime = explode(' ', microtime());
$querytime = number_format(($mtime[1] + $mtime[0] - $starttime), 6) ;
$this->sqls[] = 'Time:'.$querytime;
}
}
/**
* 选择一个数据库
*
* @param string $dbname 数据库名
*/
function select_db($dbname)
{
$this->dns['dbname'] = $dbname;
if (!@mysql_select_db($dbname, $this->link))
$this->_halt('Cannot use database '.$dbname);
}
/**
* 查询数据库版本信息
*
* @return string
*/
function version()
{
return mysql_get_server_info();
}
/**
* Ping数据库,如果无法ping通,就重连数据库
*
* @return string
*/
function ping()
{
if(!mysql_ping($this->link)) {
$this->close(); //注意:一定要先执行数据库关闭,这是关键
$this->connect();
}
}
/**
* 发送一条 MySQL 查询
*
* @param string $SQL SQL语法
* @param string $method 查询方式 [空=自动获取并缓存结果集] [unbuffer=并不获取和缓存结果的行]
* @return ms_mysql_result 资源标识符
*/
function & query($SQL, $method = '')
{
if(DEBUG) {
$mtime = explode(' ', microtime());
$starttime = $mtime[1] + $mtime[0];
$this->sqls[] = 'Query' . ($this->query_num+1) . ':' . $SQL;
}
//$this->safecheck($SQL);
if($this->dns['ping']) $this->ping();
if($method == 'unbuffer' && function_exists('mysql_unbuffered_query')) {
$query = mysql_unbuffered_query($SQL, $this->link);
} else {
$query = mysql_query($SQL, $this->link);
}
if (!$query && $method != 'SILENT') {
$this->_halt('MySQL Query Error: ' . $SQL);
return FALSE;
}
if(!is_resource($query)) return;
$this->query_num++;
if(DEBUG) {
$mtime = explode(' ', microtime());
$querytime = number_format(($mtime[1] + $mtime[0] - $starttime), 6) ;
$this->sqls[] = 'Time:'.$querytime;
if(strtolower(substr($SQL,0,7)) == 'select ' && $this->link) {
if($result = mysql_query('EXPLAIN '.$SQL, $this->link)) {
$explain = mysql_fetch_assoc($result);
$table = '';
if($explain) {
$table = '<table border="1" cellspacing="1" cellpadding="1"><tr>';
foreach(array_keys($explain) as $key) {
$table .= "<td>$key</td>";
}
$table .= '</tr><tr>';
foreach($explain as $key=>$val) {
$table .= "<td>$val</td>";
}
$table .= '</tr></table>';
}
}
}
$this->sqls[] = $table;
}
if(mysql_num_rows($query)) {
$result = new ms_mysql_result($query);
} else {
$result = FALSE;
}
return $result;
}
/**
* 执行一条 MySQL 查询
*
* @param string $SQL SQL语法
* @param string $method 查询方式 [空=自动获取并缓存结果集] [unbuffer=并不获取和缓存结果的行]
* @return resource 资源标识符
*/
function exec($SQL, $method = '')
{
if(DEBUG) {
$mtime = explode(' ', microtime());
$starttime = $mtime[1] + $mtime[0];
$this->sqls[] = 'Exec ' . ($this->query_num+1) . ':' . $SQL;
}
$this->safecheck($SQL);
if($this->dns['ping']) $this->ping();
if($method == 'unbuffer' && function_exists('mysql_unbuffered_query')) {
$query = mysql_unbuffered_query($SQL, $this->link);
} else {
$query = mysql_query($SQL, $this->link);
}
if (!$query && $method != 'SILENT') {
$this->_halt('MySQL Query Error: ' . $SQL);
}
$this->query_num++;
if(DEBUG) {
$mtime = explode(' ', microtime());
$querytime = number_format(($mtime[1] + $mtime[0] - $starttime), 6) ;
$this->sqls[] = 'Time:'.$querytime;
}
return $this->affected_rows();
}
/**
* 返回上一次执行SQL后,被影响修改的条(行)数
*
* @return int
*/
function affected_rows()
{
return mysql_affected_rows($this->link);
}
/**
* 取得上一步 INSERT 操作产生的 ID
*
* @return int
*/
function insert_id()
{
return ($id = mysql_insert_id($this->link)) >= 0 ? $id : $this->result($this->query("SELECT last_insert_id()"), 0);
}
/**
* 关闭 MySQL 连
*
* @return bool
*/
function close()
{
return mysql_close($this->link);
}
/**
* 返回上一个 MySQL 操作产生的文本错误信息
*
* @return string
*/
function error()
{
return (($this->link) ? mysql_error($this->link) : mysql_error());
}
/**
* 返回上一个 MySQL 操作中的错误信息的数字编码
*
* @return integer
*/
function errno()
{
return intval(($this->link) ? mysql_errno($this->link) : mysql_errno());
}
// 获取一个表名
function get_table($tablename)
{
if(preg_match("/^([`a-z0-9_]+)$/i", $tablename) || preg_match("/^([`a-z0-9_]+)\.([`a-z0-9_]+)$/i", $tablename)) {
return str_replace("dbpre_", $this->dns['dbpre'], $tablename);
}
redirect('无效的数据表名称:'._T($tablename));
}
function repace_table($tablename)
{
return str_replace("dbpre_", $this->dns['dbpre'], $tablename);
}
//转换插入sql的值
function _escape($str)
{
switch (gettype($str)) {
case 'boolean':
$str = ($str === FALSE) ? 0 : 1;
break;
default:
$str = "'".$this->_escape_str($str)."'";
break;
}
return $str;
}
/**
* 对字符串处理加入引号
*
* @param string $str
* @return string
*/
function _escape_str($str)
{
if (function_exists('mysql_real_escape_string')) {
return mysql_real_escape_string($str, $this->link);
} else {
return addslashes($str);
}
}
/**
* 过滤字段名
*
* @param string $field
* @return string
*/
function _ck_field($field)
{
if(preg_match("/[\'\\\"\<\>#]+/", $field)) {
show_error(lang('global_sql_invalid_field', $field));
}
foreach(array('admin','members') as $key) {
$table = $this->dns['dbpre'].$key;
if(strposex($field, $table)) show_error(lang('global_sql_invalid_field', $field));
}
return $field;
}
/**
* 显示错误信息
*
* @param string $msg
*/
function _halt($msg = '')
{
//如果设置错误捕获,则不跳出错误信息。
if($this->catch) {
return;
}
global $_G;
$message = "<html>\n<head>\n";
$message .= "<meta content=\"text/html; charset=$_G[charset]\" http-equiv=\"Content-Type\">\n";
$message .= "<link rel='stylesheet' type='text/css' href='".URLROOT."/static/images/error.css'>";
$message .= "</head>\n<body>\n";
$error = $this->error();
if(strposex($msg, $this->dns['dbpre'].'admin')) {
$message .= 'S'.'Q'.'L'.' '.'E'.'r'.'r'.'o'.'r';
} else {
$msg = str_replace($this->dns['dbpre'], '[dbpre]', $msg);
$msg = preg_replace("/[a-zA-Z0-9]{32}/i", '[md5str]', $msg);
$msg = preg_replace("/[a-zA-Z0-9]{16}/", '[hash]', $msg);
$error = str_replace($this->dns['dbpre'], '[dbpre]', $error);
$error = preg_replace("/[a-zA-Z0-9]{32}/", '[md5str]', $error);
$error = preg_replace("/[a-zA-Z0-9]{16}/", '[hash]', $error);
$message .= "<div class='error'><h3>MySQL Error:</h3>";
$message .= "<div class='error'>";
$message .= "<p><code>"._T($msg)."</code>\n";
$message .= "<b>Error description</b>: ".$error."\n<br />";
$message .= "<b>Error number</b>: ".$this->errno()."\n<br />";
$message .= "<b>Date</b>: ".date("Y-m-d @ H:i")."\n<br />";
$message .= "<b>Script</b>: http://".$_SERVER['HTTP_HOST'].getenv("REQUEST_URI")."</p>\n";
$message .= "</div>\n</div>";
$trace = debug_backtrace();
$message .= "<div class='debug'>\n<h3>Debug backtrace:</h3>";
$message .= "<table border='0' cellspacing='0' cellpadding='0' class='trace'>";
$message .= "<tr>\n<th width='400' align='left'>File</th>";
$message .= "<th width=\"50\">Line</th>";
$message .= "<th align=\"right\">Function</th>\n</tr>";
foreach($trace as $k=>$t) {
//if(!$k) continue;
$message .= "<tr><td>".str_replace(MUDDER_ROOT,'',$t['file'])."</td>";
$message .= "<td align='center'>$t[line]</td>";
$message .= "<td align='right'>".($t['class']?("{$t['class']}->"):'')."$t[function]()</td></tr>";
}
$message .= "</table>\n</div>";
}
$message .= "</body>\n</html>";
echo $message;
log_write('sqlerror',
$msg .
"\nDescription:" . $error .
"\nNumber:" . $this->errno() .
"\nDate:" . date("Y-m-d @ H:i:s") .
"\nScript:http://" . $_SERVER['HTTP_HOST'] . getenv("REQUEST_URI") .
"\nIP:" . $_G['ip'] .
"\n========================================================="
);
exit;
}
//SQL可以语句检测
function safecheck($sql) {
$result = $this->full_count_words($sql);
if($result['select'] >=4 AND $result['from'] >=3) {
log_write('sqlcheck',
htmlspecialchars($sql) .
"\nDate:" . date("Y-m-d @ H:i:s") .
"\nScript:http://" . $_SERVER['HTTP_HOST'] . getenv("REQUEST_URI") .
"\nIP:" . $this->global['ip'] .
"\n========================================================="
);
}
}
function full_count_words($str) {
$words = str_word_count($str,1);
$result = array();
foreach ($words as $w) {
$lw = strtolower($w);
if (!(isset($result[$lw]))) {
$result[$lw] = 1;
} else {
$result[$lw]++;
}
}
return $result;
}
/**
* 显示SQL查询记录
*
*/
function debug_print() {
global $_G;
if(!$this->sqls) return;
$style = 'margin:5px auto;width:98%;line-height:18px;font-family:Courier New;text-align:left;background:#eee;border-width:1px; border-style:solid;border-color:#CCC;';
$content ='<div style="'.$style.'">';
$content .='<h3 style="font-size:16px;border-bottom:1px solid #FF9900;margin:5px;padding:0 0 5px;"><a href="javascript:;" onclick="$(\'#debug_sql_history\').toggle();">SQL History</a> ('.$this->query_num.')</h3>';
$content .= '<ul style="margin:0;padding:0 0 5px;list-style:none;display:none;" id="debug_sql_history">';
foreach($this->sqls as $val) {
$content .= '<li style="padding:1px 8px;font-size:12px;">' . $val . '</li>';
}
$content .= '</ul></div>';
return $content;
}
}
class ms_mysql_result {
var $res = null;
function __construct($res) {
$this->res = $res;
}
function data_seek($row_number) {
return mysql_data_seek($this->res, row_number);
}
function mysql_db_name($row) {
return mysql_db_name($this->res, $row);
}
function result($row) {
return mysql_result($this->res, $row);
}
function fetch_array($result_type = MYSQL_ASSOC) {
//MYSQL_ASSOC,MYSQL_NUM 和 MYSQL_BOTH
return mysql_fetch_array($this->res, $result_type);
}
//获取数据,简化函数
function fetch($result_type = MYSQL_ASSOC) {
//MYSQL_ASSOC,MYSQL_NUM 和 MYSQL_BOTH
return mysql_fetch_array($this->res, $result_type);
}
function fetch_row() {
return mysql_fetch_row($this->res);
}
function fetch_assoc() {
return mysql_fetch_assoc($this->res);
}
function fetch_field($field_offset=null) {
if(!$field_offset) {
return mysql_fetch_field($this->res);
} else {
return mysql_fetch_field($this->res, field_offset);
}
}
function fetch_lengths() {
return mysql_fetch_lengths($this->res);
}
function fetch_object() {
return mysql_fetch_object($this->res);
}
function field_len($field_offset) {
return mysql_field_len($this->res, $field_offset);
}
function field_name($field_offset) {
return mysql_field_name($this->res, $field_offset);
}
function field_seek($field_offset) {
return mysql_field_seek($this->res, $field_offset);
}
function field_table($field_offset) {
return mysql_field_table($this->res, $field_offset);
}
function field_type($field_offset) {
return mysql_field_type($this->res, $field_offset);
}
function num_fields() {
return mysql_num_fields($this->res);
}
function num_rows() {
return mysql_num_rows($this->res);
}
function free_result() {
return mysql_free_result($this->res);
}
//释放SQL资源,简化函数
function free() {
return mysql_free_result($this->res);
}
}
~~~