mypdo.class.php 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. <?php
  2. /**
  3. * PDO类文件
  4. *
  5. * 数据库连接、SQL增删改语句的封装函数
  6. * SQL语句发生错误时,当调试打开,错误的SQL语句会直接输出;当调试关闭,错误的SQL会写入debug日志文件。
  7. * (数据库调试的打开与关闭在init.php文件中设置。debug日志文件在config.inc.php中有定义。)
  8. *
  9. * @createtime 2018/03/01
  10. * @author 空竹
  11. * @copyright 芝麻开发 (http://www.zhimawork.com)
  12. *
  13. * 该类的使用方法简介:
  14. *
  15. * ------------SQL查询---------
  16. * 查询带有传入参数的,先检查参数。例如:
  17. * $name = $mypdo->sql_check_input(array('string', $name));
  18. * 经过检查的参数直接嵌入SQL语句,无需添加单引号。例如:
  19. * $sql = "select * from shop where shop_name = $name ";
  20. * 执行查询:
  21. * $mypdo->sqlQuery($sql);
  22. *
  23. * ------------SQL写入---------
  24. * 示例:
  25. * $param = array(
  26. * 'id' => array('number', 999),
  27. * 'name' => array('string', 'tester')
  28. * );
  29. * $mypdo->sqlinsert('tablename', $param);
  30. *
  31. * ------------SQL修改---------
  32. * 示例:
  33. * $param = array(
  34. * 'name' => array('string', 'Test')
  35. * );
  36. * $where = array(
  37. * 'id' => array('number', 999)
  38. * );
  39. * $mypdo->sqlupdate('tablename', $param, $where);
  40. *
  41. * ------------SQL删除---------
  42. * 示例:
  43. * $where = array(
  44. * 'id' => array('number', 999)
  45. * );
  46. * $mypdo->sqldelete('tablename', $where);
  47. *
  48. */
  49. class MyPdo {
  50. public $pdo = null;
  51. public $hostname = '';
  52. public $username = '';
  53. public $database = '';
  54. public $prefix = '';
  55. public $debug = false;
  56. public $log = null;
  57. public $logSQL = false;
  58. public function __construct(){
  59. global $mylog;
  60. $this->log = $mylog;
  61. }
  62. public function dbconnect($hostname, $username, $password, $database, $prefix) {
  63. $dsn = 'mysql:dbname='.$database.';host='.$hostname.';port=3306';
  64. try {
  65. $mypdo = new PDO($dsn, $username, $password);
  66. $mypdo -> query('set names utf8;');
  67. $mypdo -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  68. $this->pdo = $mypdo;
  69. $this->prefix = $prefix;
  70. return $this;
  71. } catch(PDOException $e) {
  72. if($this->debug) echo $e->getMessage();
  73. }
  74. }
  75. //数据库调试
  76. public function debug($level = 0){
  77. switch($level){
  78. case 0:
  79. $this->debug = false;
  80. $this->logSQL = false;
  81. break;
  82. case 1:
  83. $this->debug = true;
  84. $this->logSQL = false;
  85. break;
  86. case 2:
  87. $this->debug = true;
  88. $this->logSQL = true;
  89. break;
  90. }
  91. }
  92. //查询
  93. //本函数用于执行查询语句,增删改语句请使用其他专用函数
  94. //@return 查询结果集array()。
  95. //TODO: 禁止多条查询语句同时执行;禁止增删改语句通过这个函数执行。
  96. public function sqlQuery($sql){
  97. global $CountSQLSelect;
  98. try {
  99. //统计查询语句数量2016/6/16
  100. $sqlactstr = strtolower(substr($sql, 0, 6));
  101. if($sqlactstr == 'select') $CountSQLSelect++;
  102. $rs = $this -> pdo -> query($sql);
  103. $i = 0;
  104. $data = array();
  105. foreach($rs->fetchAll() as $result) {
  106. $data[$i] = $result;
  107. $i++;
  108. }
  109. $rs->closeCursor();
  110. //2018/11/14记录SQL
  111. if($this->logSQL) {
  112. $this->log->debug($sql, 0);
  113. }
  114. return $data;
  115. } catch(PDOException $e) {
  116. $msg = $e->getMessage().'【错误的SQL语句:'.$sql.'】';
  117. if($this->debug) {
  118. echo $msg;
  119. }else{
  120. $this->log->debug($msg, 0);
  121. }
  122. }
  123. }
  124. //插入
  125. //@param $param可选值
  126. // string--表示字符串;
  127. // number--表示数字
  128. // expression--表达式
  129. //@return 成功执行返回刚插入的ID;
  130. public function sqlinsert($table, $param){
  131. if(!is_array($param)){
  132. throw new Exception('sqlinsert参数错误', 905);
  133. }
  134. $sql = 'insert into '.$table.'(';
  135. $keys = array_keys($param);
  136. $keys_str = implode(',', $keys);
  137. $sql .= $keys_str.') values(';
  138. $params = array();
  139. foreach($param as $val){
  140. $params[] = $this->sql_check_input($val);
  141. }
  142. $params_str = implode(',', $params);
  143. $sql .= $params_str.')';
  144. try {
  145. $this->pdo->exec($sql);
  146. //2018/11/14记录SQL
  147. if($this->logSQL) {
  148. $this->log->debug($sql, 0);
  149. }
  150. return $this->getLastId();
  151. } catch(PDOException $e) {
  152. $msg = $e->getMessage().'【错误的SQL语句:'.$sql.'】';
  153. if($this->debug) {
  154. echo $msg;
  155. }else{
  156. $this->log->debug($msg, 0);
  157. }
  158. }
  159. }
  160. //删除
  161. //$where的参数形式形同上面的函数sqlinsert的$param
  162. //@return 成功执行返回delete操作影响的数量
  163. public function sqldelete($table, $where){
  164. if(!is_array($where)){
  165. throw new Exception('sqldelete参数错误', 906);
  166. }
  167. $sql = 'delete from '.$table.' where ';
  168. $wheres = array();
  169. foreach($where as $key => $val){
  170. $wheres[] = $key.'='.$this->sql_check_input($val);
  171. }
  172. $wheres_str = implode(' and ', $wheres);
  173. $sql .= $wheres_str;
  174. try {
  175. $num = $this->pdo->exec($sql);
  176. //2018/11/14记录SQL
  177. if($this->logSQL) {
  178. $this->log->debug($sql, 0);
  179. }
  180. return $num;//返回删除记录数
  181. } catch(PDOException $e) {
  182. $msg = $e->getMessage().'【错误的SQL语句:'.$sql.'】';
  183. if($this->debug) {
  184. echo $msg;
  185. }else{
  186. $this->log->debug($msg, 0);
  187. }
  188. }
  189. }
  190. //修改
  191. //$where和$param的参数形式形同上面的函数sqlinsert的$param
  192. //@return 成功执行返回update操作影响的数量
  193. public function sqlupdate($table, $param, $where){
  194. if(!is_array($param)){
  195. throw new Exception('sqlupdate参数错误', 907);
  196. }
  197. $sql = 'update '.$table.' set ';
  198. $params = array();
  199. foreach($param as $key => $val){
  200. $params[] = $key.'='.$this->sql_check_input($val);
  201. }
  202. $params_str = implode(',', $params);
  203. $sql .= $params_str;
  204. $wheres = array();
  205. foreach($where as $key => $val){
  206. $wheres[] = $key.'='.$this->sql_check_input($val);
  207. }
  208. $wheres_str = implode(' and ', $wheres);
  209. $sql .= ' where '.$wheres_str;
  210. try {
  211. $num = $this->pdo->exec($sql);
  212. //2018/11/14记录SQL
  213. if($this->logSQL) {
  214. $this->log->debug($sql, 0);
  215. }
  216. return $num;//返回删除记录数
  217. } catch(PDOException $e) {
  218. $msg = $e->getMessage().'【错误的SQL语句:'.$sql.'】';
  219. if($this->debug) {
  220. echo $msg;
  221. }else{
  222. $this->log->debug($msg, 0);
  223. }
  224. }
  225. }
  226. //过滤数据,防止注入
  227. //$arr_val为数组,形如:array('string', 'abcdef')
  228. //第1个参数可接受的值为:number、string、expression
  229. public function sql_check_input($arr_val)
  230. {
  231. $value = $arr_val[1];
  232. if (get_magic_quotes_gpc())
  233. {
  234. $value = stripslashes($value);
  235. }
  236. // 如果是数字进行验证
  237. $type = $arr_val[0];
  238. if ($type == 'number'){
  239. $isint = preg_match('/^-?\d+$/', $value);
  240. $isfloat = preg_match('/^(-?\d+)(\.\d+)?$/', $value);
  241. if(!$isint && !$isfloat){
  242. throw new Exception('参数值'.$value.'应该为数字', 904);
  243. }
  244. }
  245. // 如果是字符串加引号
  246. if ($type == 'string'){
  247. $value = "'" . $this->sql_escape_mimic($value) . "'";
  248. }
  249. return $value;
  250. }
  251. //得到最后一条插入ID
  252. public function getLastId() {
  253. return $this->pdo->lastInsertId();
  254. }
  255. /**
  256. * sql_escape_mimic 用于在无mysql连接情况下替代mysql_real_escape_string的作用(防止SQL注入)
  257. *
  258. * @param mixed $str
  259. * @return
  260. */
  261. public function sql_escape_mimic($str) {
  262. if($str === '0' || $str === 0) return $str;//2016/10/10修正等于0的情况
  263. $str = strval($str);//2018/11/14修正数字当做字符传递时的情况
  264. if(!empty($str) && is_string($str)) {
  265. return str_replace(array('\\', "\0", "\n", "\r", "'", '"', "\x1a"), array('\\\\', '\\0', '\\n', '\\r', "\\'", '\\"', '\\Z'), $str);
  266. }
  267. }
  268. }
  269. ?>