discuz X2 DB数据库类详细说明

discuzX 系列的db数据库类写的已经非常好了,从性能、安全性和易用性上都做的非常优秀了。
了解discuzX 系列的db数据库类,不仅可以使我们能快速上手二次开发,也可以移植到自己的项目中来。

下面我们来分析讲解一下db数据类:

 
 
  1.  <?php
  2. class DB
  3. {
  4.  /**
  5.   * 返回表名(pre_$table)
  6.   *
  7.   * @param 原始表名 $table
  8.   * @return 增加pre之后的名字
  9.   */
  10.  function table($table) {
  11.   return DB::_execute('table_name', $table);
  12.  }
  13.  
  14.  /**
  15.   * 删除一条或者多条记录
  16.   *
  17.   * @param string $table 原始表名
  18.   * @param string $condition 数组的形式,条件语句,不需要写WHERE
  19.   * @param int $limit 删除条目数
  20.   * @param boolean $unbuffered 可以参考php自带的mysql_unbuffered_query()函数
  21.   */
  22.  function delete($table, $condition, $limit = 0, $unbuffered = true) {
  23.   if(empty($condition)) {
  24.    $where = '1';
  25.   } elseif(is_array($condition)) {
  26.    $where = DB::implode_field_value($condition, ' AND ');
  27.   } else {
  28.    $where = $condition;
  29.   }
  30.   $sql = "DELETE FROM ".DB::table($table)." WHERE $where ".($limit ? "LIMIT $limit" : '');
  31.   return DB::query($sql, ($unbuffered ? 'UNBUFFERED' : ''));
  32.  }
  33.  
  34.  /**
  35.   * 插入一条记录
  36.   *
  37.   * @param string $table 原始表名
  38.   * @param array $data 数组field->vlaue 对
  39.   * @param boolen $return_insert_id 返回 InsertID?
  40.   * @param boolen $replace 是否是REPLACE模式
  41.   * @param boolen $silent 静默方式?
  42.   * @return InsertID or Result
  43.   */
  44.  function insert($table, $data, $return_insert_id = false, $replace = false, $silent = false) {
  45.  
  46.   $sql = DB::implode_field_value($data);
  47.  
  48.   $cmd = $replace ? 'REPLACE INTO' : 'INSERT INTO';
  49.  
  50.   $table = DB::table($table);
  51.   $silent = $silent ? 'SILENT' : '';
  52.  
  53.   $return = DB::query("$cmd $table SET $sql", $silent);
  54.  
  55.   return $return_insert_id ? DB::insert_id() : $return;
  56.  
  57.  }
  58.  
  59.  /**
  60.   * 更新一条或者多条数据记录
  61.   *
  62.   * @param string $table 原始表名
  63.   * @param array $data 数据field-value
  64.   * @param string $condition 条件语句,不需要写WHERE
  65.   * @param boolean $unbuffered
  66.   * @param boolan $low_priority mysql语法,UPDATE的执行被延迟了,直到没有其它的客户端从表中读取为止
  67.   * @return result
  68.   */
  69.  function update($table, $data, $condition, $unbuffered = false, $low_priority = false) {
  70.   $sql = DB::implode_field_value($data);
  71.   $cmd = "UPDATE ".($low_priority ? 'LOW_PRIORITY' : '');
  72.   $table = DB::table($table);
  73.   $where = '';
  74.   if(empty($condition)) {
  75.    $where = '1';
  76.   } elseif(is_array($condition)) {
  77.    $where = DB::implode_field_value($condition, ' AND ');
  78.   } else {
  79.    $where = $condition;
  80.   }
  81.   $res = DB::query("$cmd $table SET $sql WHERE $where", $unbuffered ? 'UNBUFFERED' : '');
  82.   return $res;
  83.  }
  84.  
  85.  /**
  86.   * 格式化field字段和value,并组成一个字符串
  87.   *
  88.   * @param array $array 格式为 key=>value 数组
  89.   * @param 分割符 $glue
  90.   * @return string
  91.   */
  92.  function implode_field_value($array, $glue = ',') {
  93.   $sql = $comma = '';
  94.   foreach ($array as $k => $v) {
  95.    $sql .= $comma."`$k`='$v'";
  96.    $comma = $glue;
  97.   }
  98.   return $sql;
  99.  }
  100.  
  101.  /**
  102.   * 返回插入的ID
  103.   *
  104.   * @return int
  105.   */
  106.  function insert_id() {
  107.   return DB::_execute('insert_id');
  108.  }
  109.  
  110.  /**
  111.   * 依据查询结果,返回一行数据,类似 mysql_fetch_array
  112.   *
  113.   * @param resourceID $resourceid
  114.   * @return array
  115.   */
  116.  function fetch($resourceid, $type = MYSQL_ASSOC) {
  117.   return DB::_execute('fetch_array', $resourceid, $type);
  118.  }
  119.  
  120.  /**
  121.   * 依据SQL,返回一条查询结果 跟fetch一样,只是不做循环
  122.   *
  123.   * @param string $query 查询语句
  124.   * @return array
  125.   */
  126.  function fetch_first($sql) {
  127.   DB::checkquery($sql);
  128.   return DB::_execute('fetch_first', $sql);
  129.  }
  130.  
  131.  /**
  132.   * 依据查询结果,返回结果数值
  133.   *
  134.   * @param resourceid $resourceid
  135.   * @return string or int 返回结果个数 0为1个
  136.   */
  137.  function result($resourceid, $row = 0) {
  138.   return DB::_execute('result', $resourceid, $row);
  139.  }
  140.  
  141.  /**
  142.   * 依据查询语句,返回一个结果数值
  143.   *
  144.   * @param string $query SQL查询语句
  145.   * @return unknown
  146.   */
  147.  function result_first($sql) {
  148.   DB::checkquery($sql);
  149.   return DB::_execute('result_first', $sql);
  150.  }
  151.  
  152.  /**
  153.   * 执行查询
  154.   *
  155.   * @param string $sql
  156.   * @param 类型定义 $type UNBUFFERED OR SILENT
  157.   * @return Resource OR Result
  158.   */
  159.  function query($sql, $type = '') {
  160.   DB::checkquery($sql);
  161.   return DB::_execute('query', $sql, $type);
  162.  }
  163.  
  164.  /**
  165.   * 返回select的结果行数
  166.   *
  167.   * @param resource $resourceid
  168.   * @return int
  169.   */
  170.  function num_rows($resourceid) {
  171.   return DB::_execute('num_rows', $resourceid);
  172.  }
  173.  
  174.  /**
  175.   * 返回sql语句所影响的记录行数
  176.   *
  177.   * @return int
  178.   */
  179.  function affected_rows() {
  180.   return DB::_execute('affected_rows');
  181.  }
  182.  
  183.  /**
  184.   * 释放结果内存 类似mysql_free_result
  185.   *
  186.   * @return int
  187.   */
  188.  function free_result($query) {
  189.   return DB::_execute('free_result', $query);
  190.  }
  191.  
  192.  /**
  193.   * mysql_error 返回上一个 MySQL 操作产生的文本错误信息
  194.   *
  195.   * @return string
  196.   */
  197.  function error() {
  198.   return DB::_execute('error');
  199.  }
  200.  
  201.  /**
  202.   * mysql_errno 返回上一个 MySQL 操作中的错误信息的数字编码
  203.   *
  204.   * @return string
  205.   */
  206.  function errno() {
  207.   return DB::_execute('errno');
  208.  }
  209.  
  210.  /**
  211.   * 与db_mysql类方法调用的桥梁
  212.   * @param string $cmd 要调用的方法
  213.   * @param string $arg1
  214.   * @param string $arg2
  215.   * @return unknown
  216.   */
  217.  function _execute($cmd , $arg1 = '', $arg2 = '') {
  218.   static $db;
  219.   if(empty($db)) $db = & DB::object();
  220.   $res = $db->$cmd($arg1, $arg2);
  221.   return $res;
  222.  }
  223.  
  224.  /**
  225.   * 实例数据库类 支持多数据 默认mysql
  226.   *
  227.   * @return pointer of db object from discuz core
  228.   */
  229.  function &object($dbclass = 'db_mysql') {
  230.   static $db;
  231.   if(empty($db)) $db = new $dbclass();
  232.   return $db;
  233.  }
  234.  
  235.  /**
  236.   * sql查询语法 安全检查
  237.   * @param unknown_type $sql
  238.   * @return boolean
  239.   */
  240.  function checkquery($sql) {
  241.   static $status = null, $checkcmd = array('SELECT', 'UPDATE', 'INSERT', 'REPLACE', 'DELETE');
  242.   if($status === null) $status = getglobal('config/security/querysafe/status');
  243.   if($status) {
  244.    $cmd = trim(strtoupper(substr($sql, 0, strpos($sql, ' '))));
  245.    if(in_array($cmd, $checkcmd)) {
  246.     $test = DB::_do_query_safe($sql);
  247.     if($test < 1) DB::_execute('halt', 'security_error', $sql);
  248.    }
  249.   }
  250.   return true;
  251.  }
  252.  
  253.  /**
  254.   * 估计是防注入检查
  255.   * @param unknown_type $sql
  256.   * @return string|number
  257.   */
  258.  function _do_query_safe($sql) {
  259.   static $_CONFIG = null;
  260.   if($_CONFIG === null) {
  261.    $_CONFIG = getglobal('config/security/querysafe');
  262.   }
  263.  
  264.   $sql = str_replace(array('\\\\', '\\\'', '\\"', '\'\''), '', $sql);
  265.   $mark = $clean = '';
  266.   if(strpos($sql, '/') === false && strpos($sql, '#') === false && strpos($sql, '-- ') === false) {
  267.    $clean = preg_replace("/'(.+?)'/s", '', $sql);
  268.   } else {
  269.    $len = strlen($sql);
  270.    $mark = $clean = '';
  271.    for ($i = 0; $i <$len; $i++) {
  272.     $str = $sql[$i];
  273.     switch ($str) {
  274.      case '\'':
  275.       if(!$mark) {
  276.        $mark = '\'';
  277.        $clean .= $str;
  278.       } elseif ($mark == '\'') {
  279.        $mark = '';
  280.       }
  281.       break;
  282.      case '/':
  283.       if(empty($mark) && $sql[$i+1] == '*') {
  284.        $mark = '/*';
  285.        $clean .= $mark;
  286.        $i++;
  287.       } elseif($mark == '/*' && $sql[$i -1] == '*') {
  288.        $mark = '';
  289.        $clean .= '*';
  290.       }
  291.       break;
  292.      case '#':
  293.       if(empty($mark)) {
  294.        $mark = $str;
  295.        $clean .= $str;
  296.       }
  297.       break;
  298.      case "\n":
  299.       if($mark == '#' || $mark == '--') {
  300.        $mark = '';
  301.       }
  302.       break;
  303.      case '-':
  304.       if(empty($mark)&& substr($sql, $i, 3) == '-- ') {
  305.        $mark = '-- ';
  306.        $clean .= $mark;
  307.       }
  308.       break;
  309.  
  310.      default:
  311.  
  312.       break;
  313.     }
  314.     $clean .= $mark ? '' : $str;
  315.    }
  316.   }
  317.  
  318.   $clean = preg_replace("/[^a-z0-9_\-\(\)#\*\/\"]+/is", "", strtolower($clean));
  319.  
  320.   if($_CONFIG['afullnote']) {
  321.    $clean = str_replace('/**/','',$clean);
  322.   }
  323.  
  324.   if(is_array($_CONFIG['dfunction'])) {
  325.    foreach($_CONFIG['dfunction'] as $fun) {
  326.     if(strpos($clean, $fun.'(') !== false) return '-1';
  327.    }
  328.   }
  329.  
  330.   if(is_array($_CONFIG['daction'])) {
  331.    foreach($_CONFIG['daction'] as $action) {
  332.     if(strpos($clean,$action) !== false) return '-3';
  333.    }
  334.   }
  335.  
  336.   if($_CONFIG['dlikehex'] && strpos($clean, 'like0x')) {
  337.    return '-2';
  338.   }
  339.  
  340.   if(is_array($_CONFIG['dnote'])) {
  341.    foreach($_CONFIG['dnote'] as $note) {
  342.     if(strpos($clean,$note) !== false) return '-4';
  343.    }
  344.   }
  345.  
  346.   return 1;
  347.  
  348.  }
  349.  
  350. }
  351. ?>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值