<?php
class db_mysql
{
    var 
$connid;
    var 
$dbname;
    var 
$querynum 0;
    var 
$debug 1;
    var 
$search = array('/union(\s*(\/\*.*\*\/)?\s*)+select/i''/load_file(\s*(\/\*.*\*\/)?\s*)+\(/i''/into(\s*(\/\*.*\*\/)?\s*)+outfile/i');
    var 
$replace = array('union &nbsp; select''load_file &nbsp; (''into &nbsp; outfile');

    function 
connect($dbhost$dbuser$dbpw$dbname ''$pconnect 0$charset '')
    {
        
$func $pconnect == 'mysql_pconnect' 'mysql_connect';//选择连接mysql是否持久连接(而两者的区别我也是不太明白)
        
if(!$this->connid = @$func($dbhost$dbuser$dbpw))
        {
            if(
DB_NAME == '' && file_exists(PHPCMS_ROOT.'install.php'))
            {
                
header('location:./install.php');//对于数据库名字为空的话会跳转到安装那,如果自己挖过来用的话,需要改改这里啦
                
exit;
            }
            
$this->halt('Can not connect to MySQL server');//用自身的halt方法报错
            
return false;
        }
        if(
$this->version() > '4.1')
        {
            
$serverset $charset "character_set_connection='$charset',character_set_results='$charset',character_set_client=binary" '';
            
$serverset .= $this->version() > '5.0.1' ? ((empty($serverset) ? '' ',')." sql_mode='' ") : '';
            
$serverset && mysql_query("SET $serverset"$this->connid);//这里大概是设置送入数据库的字符编码吧
        
}
        if(
$dbname && !@mysql_select_db($dbname $this->connid))
        {
            
$this->halt('Cannot use database '.$dbname);//选择数据库,选不上也报错
            
return false;
        }
        
$this->dbname $dbname;//将能选择上的数据库名字赋予类中的dbname变量
        
return $this->connid;//返回连接标识号
    
}

    function 
select_db($dbname)//select_db方法也是选择数据库的功能
    
{
        if(!@
mysql_select_db($dbname $this->connid)) return false;
        
$this->dbname $dbname;
        return 
true;
    }

    function 
query($sql $type '')
    {
        
$func $type == 'UNBUFFERED' 'mysql_unbuffered_query' 'mysql_query';//选择不同的送入sql语句的方式,后者我都没用过……
        
if(!($query = @$func($sql $this->connid)) && $type != 'SILENT')//送入sql语句加判断
        
{
            
$this->halt('MySQL Query Error'$sql);//如果失败则报错
            
return false;
        }
        
$this->querynum++;//没送入一条自身的querynum变量加1
        
return $query;//返回mysql返回的数据标识集(是这样叫吧,这个东西不是数据)
    
}

    function 
select($sql$keyfield '')//注意参数都有些什么,别传错值了
    
{
        
$array = array();
        
$result $this->query($sql);//调用query方法得到那个数据标识集
        
while($r $this->fetch_array($result))//fetch_array其实就是mysql_fetch_array
        
{
            if(
$keyfield)//可以针对某个字段进行查数据
            
{
                
$key $r[$keyfield];
                
$array[$key] = $r;
            }
            else
//否则将所有的数据都放到这个数组中
            
{
                
$array[] = $r;
            }
        }
        
$this->free_result($result);//释放掉这个结果,这个方法其实就是mysql_free_result
        
return $array;//返回这个数组
    
}

    function 
insert($tablename$array)
    {
        
$this->check_fields($tablename$array);
        return 
$this->query("INSERT INTO `$tablename`(`".implode('`,`'array_keys($array))."`) VALUES('".implode("','"$array)."')");
    }

    function 
update($tablename$array$where '')//前面对这个两个检查字段的方法介绍都是为了这个方法而准备的
    
{
        
$this->check_fields($tablename$array);//check_fields
        
if($where)//如果存在where的话产生不同的sql语句
        
{
            
$sql '';
            foreach(
$array as $k=>$v)
            {
                
$sql .= ", `$k`='$v'";//拆分update的数据
            
}
            
$sql substr($sql1);//组织成一条完整而正确的sql语句(去掉前面的逗号)
            
$sql "UPDATE `$tablename` SET $sql WHERE $where";
        }
        else
        {
            
$sql "REPLACE INTO `$tablename`(`".implode('`,`'array_keys($array))."`) VALUES('".implode("','"$array)."')";
        }
        return 
$this->query($sql);
    }

    function 
get_primary($table)
    {
        
$result $this->query("SHOW COLUMNS FROM $table");
        while(
$r $this->fetch_array($result))
        {
            if(
$r['Key'] == 'PRI') break;
        }
        
$this->free_result($result);
        return 
$r['Field'];
    }

    function 
check_fields($tablename$array)
    {
        
$fields $this->get_fields($tablename);
        foreach(
$array AS $k=>$v)
        {
            if(!
in_array($k,$fields))
            {
                
$this->halt('MySQL Query Error'"Unknown column '$k' in field list");
                return 
false;
            }
        }
    }

    function 
get_fields($table)
    {
        
$fields = array();
        
$result $this->query("SHOW COLUMNS FROM $table");
        while(
$r $this->fetch_array($result))
        {
            
$fields[] = $r['Field'];
        }
        
$this->free_result($result);
        return 
$fields;
    }

    function 
get_one($sql$type ''$expires 3600$dbname '')
    {
        
$query $this->query($sql$type$expires$dbname);
        
$rs $this->fetch_array($query);
        
$this->free_result($query);
        return 
$rs ;
    }

    function 
fetch_array($query$result_type MYSQL_ASSOC)
    {
        return 
mysql_fetch_array($query$result_type);
    }

    function 
affected_rows()
    {
        return 
mysql_affected_rows($this->connid);
    }

    function 
num_rows($query)
    {
        return 
mysql_num_rows($query);
    }

    function 
num_fields($query)
    {
        return 
mysql_num_fields($query);
    }

    function 
result($query$row)
    {
        return @
mysql_result($query$row);
    }

    function 
free_result(&$query)
    {
        return 
mysql_free_result($query);
    }

    function 
insert_id()
    {
        return 
mysql_insert_id($this->connid);
    }

    function 
fetch_row($query)
    {
        return 
mysql_fetch_row($query);
    }

    function 
escape($string)
    {
        if(!
is_array($string)) return str_replace(array('\n''\r'), array(chr(10), chr(13)), mysql_real_escape_string(preg_replace($this->search$this->replace$string), $this->connid));//保证送入mysql的语句是安全的并且是能执行的(有时候你会需要它的,相信我)
        
foreach($string as $key=>$val$string[$key] = $this->escape($val);//递归使用
        
return $string;
    }

    function 
table_status($table)
    {
        return 
$this->get_one("SHOW TABLE STATUS LIKE '$table'");
    }

    function 
tables()
    {
        
$tables = array();
        
$result $this->query("SHOW TABLES");
        while(
$r $this->fetch_array($result))
        {
            
$tables[] = $r['Tables_in_'.$this->dbname];
        }
        
$this->free_result($result);
        return 
$tables;
    }

    function 
table_exists($table)
    {
        
$tables $this->tables($table);
        return 
in_array($table$tables);
    }

    function 
field_exists($table$field)
    {
        
$fields $this->get_fields($table);
        return 
in_array($field$fields);
    }

    function 
version()
    {
        return 
mysql_get_server_info($this->connid);
    }

    function 
close()
    {
        return 
mysql_close($this->connid);
    }

    function 
error()
    {
        return @
mysql_error($this->connid);
    }

    function 
errno()
    {
        return 
intval(@mysql_errno($this->connid)) ;
    }

    function 
halt($message ''$sql '')
    {
        
$this->errormsg "<b>MySQL Query : </b>$sql <br /><b> MySQL Error : </b>".$this->error()." <br /> <b>MySQL Errno : </b>".$this->errno()." <br /><b> Message : </b> $message";
        if(
$this->debug)//你当然可以设置关掉这个显示更详细信息的功能
        
{
            
$msg = (defined('IN_ADMIN') || DEBUG) ? $this->errormsg "Bad Request. $LANG[illegal_request_return]";//额..这句代码可以kill吧,因为如果我们自己用的话就不是这样的了
            
echo '<div style="font-size:12px;text-align:left; border:1px solid #9cc9e0; padding:1px 4px;color:#000000;font-family:Arial, Helvetica,sans-serif;"><span>'.$msg.'</span></div>';//为了显示美观点所以加上了一大段style
            
exit;
        }
    }
}
?>