解析phpcms数据库连接类

来源:互联网 发布:java 反射 混淆 编辑:程序博客网 时间:2024/05/16 16:57

很久之前的了,还是贴在这吧留作纪念。 

2009-10-22

链接mysql数据库
=============================================持久连接 =========================================================
mysql_pconnect
(PHP 3, PHP 4 )

mysql_pconnect --  打开一个到 MySQL 服务器的持久连接
说明
resource mysql_pconnect ( [string server [, string username [, string password [, int client_flags]]]])


如果成功则返回一个正的 MySQL 持久连接标识符,出错则返回 FALSE。

mysql_pconnect() 建立一个到 MySQL 服务器的连接。如果没有提供可选参数,则使用如下默认值:server = 'localhost:3306',

username = 服务器进程所有者的用户名,password = 空密码。client_flags 参数可以是以下常量的组合:MYSQL_CLIENT_COMPRESS

,MYSQL_CLIENT_IGNORE_SPACE 或者 MYSQL_CLIENT_INTERACTIVE。

server 参数也可以包括端口号,例如 "hostname:port",或者是本机套接字的的路径,例如 ":/path/to/socket"。

注: 对 ":port" 的支持是 3.0B4 版添加的。

对 ":/path/to/socket" 的支持是 3.0.10 版添加的。


mysql_pconnect() 和 mysql_connect() 非常相似,但有两个主要区别。

首先,当连接的时候本函数将先尝试寻找一个在同一个主机上用同样的用户名和密码已经打开的(持久)连接,如果找到,则返回此

连接标识而不打开新连接。

其次,当脚本执行完毕后到 SQL 服务器的连接不会被关闭,此连接将保持打开以备以后使用(mysql_close() 不会关闭由

mysql_pconnect() 建立的连接)。

可选参数 client_flags 自 PHP 4.3.0 版起可用。

此种连接称为“持久的”。
永久的数据库连接是指在您的脚本结束运行时不关闭的连接。当收到一个永久连接的请求时。PHP 将检查是否已经存在一个(前面已

经开启的)相同的永久连接。如果存在,将直接使用这个连接;如果不存在,则建立一个新的连接。所谓“相同”的连接是指用相同

的用户名和密码到相同主机的连接。

对 WEB 服务器的工作和分布负载没有完全理解的读者可能会错误地理解永久连接的作用。特别的,永久连接不会在相同的连接上为

您提供建立“用户会话”的能力,也不提供有效建立事务的能力。实际上,从严格意义上来讲,永久连接不会给您提供任何非永久连

接无法提供的特殊功能。

为什么?

这和 WEB 服务器工作的方式有关。您的 WEB 服务器可以用三种方法来利用 PHP 生成 WEB 页面。

第一种方法是将 PHP 用作一个“外壳”。以这种方法运行,PHP 会为向您的 WEB 服务器提出的每个 PHP 页面请求生成并结束一个

PHP 解释器线程。由于该线程会随每个请求的结束而结束,因此任何在这个线程中利用的任何资源(例如指向 SQL 数据库服务器的

连接)都会随线程的结束而关闭。在这种情况下,您使用永久连接不会获得任何地改变――因为它们根本不是永久的。

第二,也是最常用的方法,是把 PHP 用作多过程 WEB 服务器的一个模块,这种方法目前只适用于 Apache。对于一个多过程的服务

器,其典型特征是有一个父过程和一组子过程协调运行,其中实际生成 WEB 页面的是子过程。每当客户端向父过程提出请求时,该

请求会被传递给还没有被其它的客户端请求占用的子过程。这也就是说当相同的客户端第二次向服务端提出请求时,它将有可能被一

个不同的子过程来处理。在开启了一个永久连接后,所有请求 SQL 服务的后继页面都能够重新使用这个已经建立的 SQL Server 连

接。

最后一种方法是将 PHP 用作多线程 WEB 服务器的一个插件。目前 PHP 4 已经支持 ISAPI、WSAPI 和 NSAPI(在 Windows 环境下)

,这些使得 PHP 可以被用作诸如 Netscape FastTrack (iPlanet)、Microsoft's Internet Information Server (IIS) 和

O'Reilly's WebSite Pro 等多线程 WEB 服务器的插件。永久连接的行为和前面所描述的多过程模型在本质上是相同的。注意 PHP 3

不支持 SAPI。

如果永久连接并没有任何附加的功能,那么我们使用它有什么好处?

答案非常简单――效率。当客户端对您的 SQL 服务器的连接请求非常频繁时,永久连接将更加高效。连接请求频繁的标准取决于很

多因素。例如,数据库的种类,数据库服务和 WEB 服务是否在同一台服务器上,SQL 服务器如何加载负载等。但我们至少知道,当

连接请求很频繁时,永久连接将显著的提高效率。它使得每个子过程在其生命周期中只做一次连接操作,而非每次在处理一个页面时

都要向 SQL 服务器提出连接请求。这也就是说,每个子过程将对服务器建立各自独立的永久连接。例如,如果您有 20 个不同的子

过程运行某脚本建立了永久的 SQL 服务器永久连接,那么实际上您向该 SQL 服务器建立了 20 个不同的永久连接,每个过程占有一

个。

注意,如果永久连接的子过程数目超过了您设定的数据库连接数限制,系统将会产生一些缺陷。如果您的数据库的同时连接数限制为

16,而在繁忙会话的情况下,有 17 个线程试图连接,那么有一个线程将无法连接。如果这个时候,在您的脚本中出现了使得连接无

法关闭的错误(例如无限循环),则该数据库的 16 个连接将迅速的受到影响。请查阅您使用的数据库的文档,以获取关于如何处理

已放弃的及闲置的连接的方法。


警告
在使用永久连接时还有一些特别的问题需要注意。例如在永久连接中使用数据表锁时,如果脚本不管什么原因无法释放该数据表锁,

其随后使用相同连接的脚本将会被永久的阻塞,使得您需要重新启动 httpd 服务或者数据库服务。另外,在使用事务处理时,如果

脚本在事务阻塞产生前结束,则该阻塞也会影响到使用相同连接的下一个脚本。不管在什么情况下,您都可以通过使用

register_shutdown_function() 函数来注册一个简单的清理函数来打开数据表锁,或者滚回事务。或者更好的处理方法,是不在使

用数据表锁或者事务处理的脚本中使用永久连接,这可以从根本上解决这个问题(当然您也可以在其它地方使用永久连接)。
 

以下是一点重要的总结。永久连接是为通常连接建立一对一的分布而设计的。这意味着您必须能够保证在将永久连接替换为非永久连

接时,您脚本的行为不会改变。使用永久连接将(非常)有可能改变您脚本的效率,但不改变其行为!

===============================mysql_unbuffered_query ( string query [, resource link_identifier])

===================
mysql_unbuffered_query() 向 MySQL 发送一条 SQL 查询 query,但不像 mysql_query() 那样自动获取并缓存结果集。一方面,这

在处理很大的结果集时会节省可观的内存。另一方面,可以在获取第一行后立即对结果集进行操作,而不用等到整个 SQL 语句都执

行完毕。当使用多个数据库连接时,必须指定可选参数 link_identifier。

注: mysql_unbuffered_query() 的好处是有代价的:在 mysql_unbuffered_query() 返回的结果集之上不能使用 mysql_num_rows()

和 mysql_data_seek()。此外在向 MySQL 发送一条新的 SQL 查询之前,必须提取掉所有未缓存的 SQL 查询所产生的结果行。
resource mysql_query ( string query [, resource link_identifier])


mysql_query() 向与指定的连接标识符关联的服务器中的当前活动数据库发送一条查询。如果没有指定 link_identifier,则使用上

一个打开的连接。如果没有打开的连接,本函数会尝试无参数调用 mysql_connect() 函数来建立一个连接并使用之。查询结果会被

缓存。

注: 查询字符串不应以分号结束。

mysql_query() 仅对 SELECT,SHOW,EXPLAIN 或 DESCRIBE 语句返回一个资源标识符,如果查询执行不正确则返回 FALSE。对于其

它类型的 SQL 语句,mysql_query() 在执行成功时返回 TRUE,出错时返回 FALSE。非 FALSE 的返回值意味着查询是合法的并能够

被服务器执行。这并不说明任何有关影响到的或返回的行数。 很有可能一条查询执行成功了但并未影响到或并未返回任何行。

以下查询语法上有错,因此 mysql_query() 失败并返回 FALSE:
举例:

   $link = mysql_connect('localhost','root','');
mysql_select_db('test');
$sql = "SHOW COLUMNS FROM test";

 

//$result = mysql_unbuffered_query($sql,$link);
$result = mysql_query($sql,$link);

while ($row = mysql_fetch_array($result)) {
 printf (" %s ", $row['key']);
}

mysql_data_seek($result,0);

 while ($row = mysql_fetch_array($result))
  {
     printf ("%s", $row['key']);
  }

   mysql_free_result($result);
============================OK============================
<?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 == 1 ? 'mysql_pconnect' : 'mysql_connect';
  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');
   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;
  return $this->connid;
 }

 function select_db($dbname)
 {
  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';//是否对查询结果缓存
  if(!($query = @$func($sql , $this->connid)) && $type != 'SILENT')
  {
   $this->halt('MySQL Query Error', $sql);
   return false;
  }
  $this->querynum++;
  return $query;
 }

 function select($sql, $keyfield = '')
 {
  $array = array();
  $result = $this->query($sql);
  while($r = $this->fetch_array($result))
  {
   if($keyfield)
   {
    $key = $r[$keyfield];
    $array[$key] = $r;
   }
   else
   {
    $array[] = $r;
   }
  }
  $this->free_result($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);
  if($where)
  {
   $sql = '';
   foreach($array as $k=>$v)
   {
    $sql .= ", `$k`='$v'";
   }
   $sql = substr($sql, 1);
   $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);//取得被 INSERT,UPDATE 或者 DELETE 查询所影响到的行的数目
 }

 function num_rows($query)
 {
  return mysql_num_rows($query);//返回结果集中行的数目。此命令仅对 SELECT 语句有效。要取得被 INSERT,

UPDATE 或者 DELETE 查询所影响到的行的数目
 }

 function num_fields($query)
 {
  return mysql_num_fields($query);//返回结果集中字段的数目。
 }

 function result($query, $row)
 {
  return @mysql_result($query, $row);//回 MySQL 结果集中一个单元的内容。 取得结果数据
 }

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

 function insert_id()
 {
  return mysql_insert_id($this->connid);//返回给定的 link_identifier 中上一步 INSERT 查询中产生的

AUTO_INCREMENT 的 ID 号。
 }

 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));
  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);//返回mysql版本。
 }

 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]";
   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>';
   exit;
  }
 }
}
?>