欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

加强版phplib的DB类

程序员文章站 2023-01-24 19:52:02
复制代码 代码如下:
复制代码 代码如下:

<?php
/****************************************************************************************************************
为了便于自己的开发,又不想使用adodb、pear::db这样的庞然大物,
就用在phplib db类的基础上、参考pear::db类,封装的db类,简单好使,非常方便。
mysql有效

[ 连接数据库 ]

//包含数据库处理类文件
include_once("database.inc.php");

//本地数据库配置
define("db_host",    "localhost"); //数据库服务器
define("db_user_name",   "root");  //数据库用户名
define("db_user_pass",   "");   //密码
define("db_database",   "test");  //数据库

//连接本地数据库
$db = new db_sql();
$db->connect(db_database, db_host, db_user_name, db_user_pass);

[ 使用方法 ]

//获取所有记录
$sql = "select * from table1";
$all_record = $db->get_all($sql);

//获取一条
$sql = "select * from table1 where id = '1'";
$one_row = $db->get_one($sql);

//分页查询,提取20条记录
$sql = "select * from table1";
$page_record = $db->limit_query($sql, $start=0, $offset=20, $order="order by id desc");

//提取指定数目的记录
$sql = "select * from table1";
$limit_record = $db->get_limit($sql,10);

//统计记录数,统计所有类型为学生的
$count = $db->count("table1", "id", "type = 'student'");

//插入一条记录
$info_array = array(
  "name"  => "heiyeluren",
  "type"  => "student",
  "age"  => "22",
  "gender" => "boy"
 );
$db->insert("table1", $info_array);

//更新一条记录
$info_array = array(
  "name"  => "heiyeluren",
  "type"  => "teacher",
  "age"  => "22",
  "gender" => "boy"
 );
$db->update("table1", $info_array, "name = 'heiyeluren'");

//删除记录
$db->delete("table1", "name = 'heiyeluren'");

//执行一条无结果集的sql
$db->execute("delete from table1 where name = 'heiyeluren'");

********************************************************************************************************/

/**
 * 文件: database.inc.php
 * 描述: 数据库操作类
 * 说明: 本库使用phplib db库作为核心, 同时增加一些实用方法, 详细参考注释
 */

class db_sql 
{

  /* public: connection parameters */
  var $host     = "";
  var $database = "";
  var $user     = "";
  var $password = "";

  /* public: configuration parameters */
  var $auto_free     = 1;     ## set to 1 for automatic mysql_free_result()
  var $debug         = 0;     ## set to 1 for debugging messages.
  var $halt_on_error = "yes"; ## "yes" (halt with message), "no" (ignore errors quietly), "report" (ignore errror, but spit a warning)
  var $pconnect      = 0;     ## set to 1 to use persistent database connections
  var $seq_table     = "db_sequence";

  /* public: result array and current row number */
  var $record   = array();
  var $row;

  /* public: current error number and error text */
  var $errno    = 0;
  var $error    = "";

  /* public: this is an api revision, not a cvs revision. */
  var $type     = "mysql";
  //var $revision = "1.2";

  /* private: link and query handles */
  var $link_id  = 0;
  var $query_id = 0;

  var $locked   = false;      ## set to true while we have a lock

  /* public: constructor */
  function db_sql() {
    $this->query($query);
  }

  /* public: some trivial reporting */
  function link_id() {
    return $this->link_id;
  }

  function query_id() {
    return $this->query_id;
  }

  /* public: connection management */
  function connect($database = "", $host = "", $user = "", $password = "") {
    /* handle defaults */
    if ("" == $database) 
      $database = $this->database;

    if ("" == $host) 
      $host     = $this->host;

    if ("" == $user) 
      $user     = $this->user;

    if ("" == $password) 
      $password = $this->password;

      
    /* establish connection, select database */
    if ( 0 == $this->link_id ) {

      if(!$this->pconnect) {
        $this->link_id = mysql_connect($host, $user, $password);
      } else {
        $this->link_id = mysql_pconnect($host, $user, $password); 
      }
      if (!$this->link_id) {
        $this->halt("connect($host, $user, \$password) failed.");
        return 0;
      }

      if (!@mysql_select_db($database,$this->link_id)) {
        $this->halt("cannot use database ".$database);
        return 0;
      }
    }

    return $this->link_id;
  }

  /* public: discard the query result */
  function free() {
      @mysql_free_result($this->query_id);
      $this->query_id = 0;
  }

  /* public: perform a query */
  function query($query_string) {
    /* no empty queries, please, since php4 chokes on them. */
    if ($query_string == "")
      /* the empty query string is passed on from the constructor,
       * when calling the class without a query, e.g. in situations
       * like these: '$db = new db_sql_subclass;'
       */
      return 0;

    if (!$this->connect()) {
      return 0; /* we already complained in connect() about that. */
    };

    # new query, discard previous result.
    if ($this->query_id) {
      $this->free();
    }

    if ($this->debug)
      printf("debug: query = %s<br>\n", $query_string);

    $this->query_id = @mysql_query($query_string,$this->link_id);
    $this->row   = 0;
    $this->errno = mysql_errno();
    $this->error = mysql_error();
    if (!$this->query_id) {
      $this->halt("invalid sql: ".$query_string);
    }

    # will return nada if it fails. that's fine.
    return $this->query_id;
  }

  /* public: walk result set */
  function next_record() {
    if (!$this->query_id) {
      $this->halt("next_record called with no query pending.");
      return 0;
    }

    $this->record = @mysql_fetch_array($this->query_id);
    $this->row   += 1;
    $this->errno  = mysql_errno();
    $this->error  = mysql_error();

    $stat = is_array($this->record);
    if (!$stat && $this->auto_free) {
      $this->free();
    }
    return $stat;
  }

  /* public: position in result set */
  function seek($pos = 0) {
    $status = @mysql_data_seek($this->query_id, $pos);
    if ($status)
      $this->row = $pos;
    else {
      $this->halt("seek($pos) failed: result has ".$this->num_rows()." rows.");

      /* half assed attempt to save the day, 
       * but do not consider this documented or even
       * desireable behaviour.
       */
      @mysql_data_seek($this->query_id, $this->num_rows());
      $this->row = $this->num_rows();
      return 0;
    }

    return 1;
  }

  /* public: table locking */
  function lock($table, $mode = "write") {
    $query = "lock tables ";
    if(is_array($table)) {
      while(list($key,$value) = each($table)) {
        // text keys are "read", "read local", "write", "low priority write"
        if(is_int($key)) $key = $mode;
        if(strpos($value, ",")) {
          $query .= str_replace(",", " $key, ", $value) . " $key, ";
        } else {
          $query .= "$value $key, ";
        }
      }
      $query = substr($query, 0, -2);
    } elseif(strpos($table, ",")) {
      $query .= str_replace(",", " $mode, ", $table) . " $mode";
    } else {
      $query .= "$table $mode";
    }
    if(!$this->query($query)) {
      $this->halt("lock() failed.");
      return false;
    }
    $this->locked = true;
    return true;
  }

  function unlock() {

    // set before unlock to avoid potential loop
    $this->locked = false;

    if(!$this->query("unlock tables")) {
      $this->halt("unlock() failed.");
      return false;
    }
    return true;
  }

  /* public: evaluate the result (size, width) */
  function affected_rows() {
    return @mysql_affected_rows($this->link_id);
  }

  function num_rows() {
    return @mysql_num_rows($this->query_id);
  }

  function num_fields() {
    return @mysql_num_fields($this->query_id);
  }

  /* public: shorthand notation */
  function nf() {
    return $this->num_rows();
  }

  function np() {
    print $this->num_rows();
  }

  function f($name) {
    if (isset($this->record[$name])) {
      return $this->record[$name];
    }
  }

  function p($name) {
    if (isset($this->record[$name])) {
      print $this->record[$name];
    }
  }

  /* public: sequence numbers */
  function nextid($seq_name) {
    /* if no current lock, lock sequence table */
    if(!$this->locked) {
      if($this->lock($this->seq_table)) {
        $locked = true;
      } else {
        $this->halt("cannot lock ".$this->seq_table." - has it been created?");
        return 0;
      }
    }

    /* get sequence number and increment */
    $q = sprintf("select nextid from %s where seq_name = '%s'",
               $this->seq_table,
               $seq_name);
    if(!$this->query($q)) {
      $this->halt('query failed in nextid: '.$q);
      return 0;
    }

    /* no current value, make one */
    if(!$this->next_record()) {
      $currentid = 0;
      $q = sprintf("insert into %s values('%s', %s)",
                 $this->seq_table,
                 $seq_name,
                 $currentid);
      if(!$this->query($q)) {
        $this->halt('query failed in nextid: '.$q);
        return 0;
      }
    } else {
      $currentid = $this->f("nextid");
    }
    $nextid = $currentid + 1;
    $q = sprintf("update %s set nextid = '%s' where seq_name = '%s'",
               $this->seq_table,
               $nextid,
               $seq_name);
    if(!$this->query($q)) {
      $this->halt('query failed in nextid: '.$q);
      return 0;
    }

    /* if nextid() locked the sequence table, unlock it */
    if($locked) {
      $this->unlock();
    }

    return $nextid;
  }

  /* public: return table metadata */
  function metadata($table = "", $full = false) {
    $count = 0;
    $id    = 0;
    $res   = array();

    /*
     * due to compatibility problems with table we changed the behavior
     * of metadata();
     * depending on $full, metadata returns the following values:
     *
     * - full is false (default):
     * $result[]:
     *   [0]["table"]  table name
     *   [0]["name"]   field name
     *   [0]["type"]   field type
     *   [0]["len"]    field length
     *   [0]["flags"]  field flags
     *
     * - full is true
     * $result[]:
     *   ["num_fields"] number of metadata records
     *   [0]["table"]  table name
     *   [0]["name"]   field name
     *   [0]["type"]   field type
     *   [0]["len"]    field length
     *   [0]["flags"]  field flags
     *   ["meta"][field name]  index of field named "field name"
     *   this last one could be used if you have a field name, but no index.
     *   test:  if (isset($result['meta']['myfield'])) { ...
     */

    // if no $table specified, assume that we are working with a query
    // result
    if ($table) {
      $this->connect();
      $id = @mysql_list_fields($this->database, $table);
      if (!$id) {
        $this->halt("metadata query failed.");
        return false;
      }
    } else {
      $id = $this->query_id; 
      if (!$id) {
        $this->halt("no query specified.");
        return false;
      }
    }

    $count = @mysql_num_fields($id);

    // made this if due to performance (one if is faster than $count if's)
    if (!$full) {
      for ($i=0; $i<$count; $i++) {
        $res[$i]["table"] = @mysql_field_table ($id, $i);
        $res[$i]["name"]  = @mysql_field_name  ($id, $i);
        $res[$i]["type"]  = @mysql_field_type  ($id, $i);
        $res[$i]["len"]   = @mysql_field_len   ($id, $i);
        $res[$i]["flags"] = @mysql_field_flags ($id, $i);
      }
    } else { // full
      $res["num_fields"]= $count;

      for ($i=0; $i<$count; $i++) {
        $res[$i]["table"] = @mysql_field_table ($id, $i);
        $res[$i]["name"]  = @mysql_field_name  ($id, $i);
        $res[$i]["type"]  = @mysql_field_type  ($id, $i);
        $res[$i]["len"]   = @mysql_field_len   ($id, $i);
        $res[$i]["flags"] = @mysql_field_flags ($id, $i);
        $res["meta"][$res[$i]["name"]] = $i;
      }
    }

    // free the result only if we were called on a table
    if ($table) {
      @mysql_free_result($id);
    }
    return $res;
  }

  /* public: find available table names */
  function table_names() {
    $this->connect();
    $h = @mysql_query("show tables", $this->link_id);
    $i = 0;
    while ($info = @mysql_fetch_row($h)) {
      $return[$i]["table_name"]      = $info[0];
      $return[$i]["tablespace_name"] = $this->database;
      $return[$i]["database"]        = $this->database;
      $i++;
    }

    @mysql_free_result($h);
    return $return;
  }

  /* private: error handling */
  function halt($msg) {
    $this->error = @mysql_error($this->link_id);
    $this->errno = @mysql_errno($this->link_id);

    if ($this->locked) {
      $this->unlock();
    }

    if ($this->halt_on_error == "no")
      return;

    $this->haltmsg($msg);

    if ($this->halt_on_error != "report")
      die("session halted.");
  }

  function haltmsg($msg) {
    printf("</td></tr></table><b>database error:</b> %s<br>\n", $msg);
    printf("<b>mysql error</b>: %s (%s)<br>\n",
      $this->errno,
      $this->error);
  }

 
 //----------------------------------
 // 模块: 自定义函数
 // 功能: 部分实用的数据库处理方法
 // 作者: heiyeluren
 // 时间: 2005-12-26
 //----------------------------------

 /**
  * 方法: execute($sql)
  * 功能: 执行一条sql语句,主要针对没有结果集返回的sql
  * 参数: $sql 需要执行的sql语句,例如:execute("delete from table1 where id = '1'")
  * 返回: 更新成功返回true,失败返回false
  */
 function execute($sql)
 {
  if (empty($sql))
  {
   $this->error("invalid parameter");
  }
  if (!$this->query($sql))
  {
   return false;
  }
  return true;
 }

 /**
  * 方法: get_all($sql)
  * 功能: 获取sql执行的所有记录
  * 参数: $sql  需要执行的sql,例如: get_all("select * from table1")
  * 返回: 返回包含所有查询结果的二维数组
  */
 function get_all($sql)
 {
  $this->query($sql);
  $result_array = array();
  while($this->next_record())
  {

   $result_array[] = $this->record;
  }
  if (count($result_array)<=0)
  {
   return 0;
  }
  return $result_array;
 }

 /**
  * 方法: get_one($sql)
  * 功能: 获取sql执行的一条记录
  * 参数: $sql 需要执行的sql,例如: get_one("select * from table1 where id = '1'")
  * 返回: 返回包含一条查询结果的一维数组
  */
 function get_one($sql)
 {
  $this->query($sql);
  if (!$this->next_record())
  {
   return 0;
  }
  return $this->record;
 }

 /**
  * 方法: get_limit($sql, $limit)
  * 功能: 获取sql执行的指定数量的记录
  * 参数: 
  * $sql  需要执行的sql,例如: select * from table1
  * $limit 需要限制的记录数
  * 例如  需要获取10条记录, get_limit("select * from table1", 10);
  *
  * 返回: 返回包含所有查询结果的二维数组
  */
 function get_limit($sql, $limit)
 {
  $this->query($sql);
  $result_array = array();
  for ($i=0; $i<$limit&&$this->next_record(); $i++)
  {
   $result_array[] = $this->record;
  }
  if (count($result_array) <= 0)
  {
   return 0;
  }
  return $result_array;
 }

 /**
  * 方法: limit_query($sql, $start=0, $offset=20, $order="")
  * 功能: 为分页的获取sql执行的指定数量的记录
  * 参数: 
  * $sql  需要执行的sql,例如: select * from table1
  * $start 记录的开始数, 缺省为0
  * $offset 记录的偏移量,缺省为20
  * $order 排序方式,缺省为空,例如:order by id desc
  * 例如  需要获取从0到10的记录并且按照id号倒排, get_limit("select * from table1", 0, 10, "order by id desc");
  *
  * 返回: 返回包含所有查询结果的二维数组
  */
 function limit_query($sql, $start=0, $offset=20, $order="")
 {
  $sql = $sql ." $order  limit $start,$offset";
  $this->query($sql);
  $result = array();
  while($this->next_record())
  {
   $result[] = $this->record;
  }
  if (count($result) <=0 )
  {
   return 0;
  }
  return $result;
 }

 /**
  * 方法: count($table,$field="*", $where="")
  * 功能: 统计表中数据总数
  * 参数: 
  * $table 需要统计的表名
  * $field 需要统计的字段,默认为*
  * $where 条件语句,缺省为空
  * 例如  按照id统计所有年龄小于20岁的用户, count("user_table", "id", "user_age < 20")
  *
  * 返回: 返回统计结果的数字
  */
 function count($table,$field="*", $where="")
 {
  $sql = (empty($where) ? "select count($field) from $table" : "select count($field) from $table where $where");
  $result = $this->get_one($sql);
  if (!is_array($result))
  {
   return 0;
  }
  return $result[0];
 }

 /**
  * 方法: insert($table,$dataarray)
  * 功能: 插入一条记录到表里
  * 参数: 
  * $table  需要插入的表名
  * $dataarray 需要插入字段和值的数组,键为字段名,值为字段值,例如:array("user_name"=>"张三", "user_age"=>"20岁");
  * 例如   比如插入用户张三,年龄为20, insert("users", array("user_name"=>"张三", "user_age"=>"20岁"))
  *
  * 返回: 插入记录成功返回true,失败返回false
  */
 function insert($table,$dataarray)
 {
  if (!is_array($dataarray) || count($dataarray)<=0)
  {
   $this->error("invalid parameter");
  }
  while(list($key,$val) = each($dataarray))
  {
   $field .= "$key,";
   $value .= "'$val',";
  }
  $field = substr($field, 0, -1);
  $value = substr($value, 0, -1);
  $sql = "insert into $table ($field) values ($value)";
  if (!$this->query($sql))
  {
   return false;
  }
  return true;
 }

 /**
  * 方法: update($talbe, $dataarray, $where)
  * 功能: 更新一条记录
  * 参数: 
  * $table  需要更新的表名
  * $dataarray 需要更新字段和值的数组,键为字段名,值为字段值,例如:array("user_name"=>"张三", "user_age"=>"20岁");
  * $where  条件语句
  * 例如   比如更新姓名为张三的用户为李四,年龄为21
  *    update("users",  array("user_name"=>"张三", "user_age"=>"20岁"),  "user_name='张三'")
  *
  * 返回: 更新成功返回true,失败返回false
  */
 function update($talbe, $dataarray, $where)
 {
  if (!is_array($dataarray) || count($dataarray)<=0)
  {
   $this->error("invalid parameter");
  }
  while(list($key,$val) = each($dataarray))
  {
   $value .= "$key = '$val',";
  }
  $value = substr($value, 0, -1);
  $sql = "update $talbe set $value where $where";
  if (!$this->query($sql))
  {
   return false;
  }
  return true;
 }

 /**
  * 方法: delete($table, $where)
  * 功能: 删除一条记录
  * 参数: 
  * $table  需要删除记录的表名
  * $where  需要删除记录的条件语句
  * 例如   比如要删除用户名为张三的用户,delete("users",  "user_name='张三'")
  *
  * 返回: 更新成功返回true,失败返回false
  */
 function delete($table, $where)
 {
  if (empty($where))
  {
   $this->error("invalid parameter");
  }
  $sql = "delete from $table where $where";
  if (!$this->query($sql))
  {
   return false;
  }
  return true;
 }

 /**
  * 方法: error($msg="")
  * 功能: 显示错误信息后中止脚本
  * 参数: $msg 需要显示的错误信息
  * 返回: 无返回
  */
 function error($msg="")
 {
  echo "<strong>error</strong>: $msg\n<br>\n";
  exit();
 }

 /**
  * 方法:get_insert_id()
  * 功能:获取最后插入的id
  * 参数: 无参数
  * 返回:关闭成功返回id,失败返回0
  */
 function get_insert_id()
 {
  return mysql_insert_id($this->link_id);
 }

 /**
  * 方法:close()
  * 功能:关闭当前数据库连接
  * 参数: 无参数
  * 返回:关闭成功返回true,失败返回false
  */
 function close()
 {
  return mysql_close($this->link_id);
 } 
}
?>