mypdo.class.php 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  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 $sql
  126. * @return mixed
  127. * 执行sql
  128. */
  129. public function execSql($sql)
  130. {
  131. try {
  132. $mypdo = new MyPdo();//这里框架中的pdo不能用
  133. $mypdo->exec($sql);//2018/11/14记录SQL
  134. if($this->logSQL) {
  135. $this->log->debug($sql, 0);
  136. }
  137. return $this->getLastId();
  138. } catch(PDOException $e) {
  139. $msg = $e->getMessage().'【错误的SQL语句:'.$sql.'】';
  140. if($this->debug) {
  141. echo $msg;
  142. }else{
  143. $this->log->debug($msg, 0);
  144. }
  145. }
  146. }
  147. //插入
  148. //@param $param可选值
  149. // string--表示字符串;
  150. // number--表示数字
  151. // expression--表达式
  152. //@return 成功执行返回刚插入的ID;
  153. public function sqlinsert($table, $param){
  154. if(!is_array($param)){
  155. throw new Exception('sqlinsert参数错误', 905);
  156. }
  157. $sql = 'insert into '.$table.'(';
  158. $keys = array_keys($param);
  159. $keys_str = implode(',', $keys);
  160. $sql .= $keys_str.') values(';
  161. $params = array();
  162. foreach($param as $val){
  163. $params[] = $this->sql_check_input($val);
  164. }
  165. $params_str = implode(',', $params);
  166. $sql .= $params_str.')';
  167. var_dump($sql);
  168. try {
  169. $this->pdo->exec($sql);
  170. //2018/11/14记录SQL
  171. if($this->logSQL) {
  172. $this->log->debug($sql, 0);
  173. }
  174. return $this->getLastId();
  175. } catch(PDOException $e) {
  176. $msg = $e->getMessage().'【错误的SQL语句:'.$sql.'】';
  177. if($this->debug) {
  178. echo $msg;
  179. }else{
  180. $this->log->debug($msg, 0);
  181. }
  182. }
  183. }
  184. //删除
  185. //$where的参数形式形同上面的函数sqlinsert的$param
  186. //@return 成功执行返回delete操作影响的数量
  187. public function sqldelete($table, $where){
  188. if(!is_array($where)){
  189. throw new Exception('sqldelete参数错误', 906);
  190. }
  191. $sql = 'delete from '.$table.' where ';
  192. $wheres = array();
  193. foreach($where as $key => $val){
  194. $wheres[] = $key.'='.$this->sql_check_input($val);
  195. }
  196. $wheres_str = implode(' and ', $wheres);
  197. $sql .= $wheres_str;
  198. try {
  199. $num = $this->pdo->exec($sql);
  200. //2018/11/14记录SQL
  201. if($this->logSQL) {
  202. $this->log->debug($sql, 0);
  203. }
  204. return $num;//返回删除记录数
  205. } catch(PDOException $e) {
  206. $msg = $e->getMessage().'【错误的SQL语句:'.$sql.'】';
  207. if($this->debug) {
  208. echo $msg;
  209. }else{
  210. $this->log->debug($msg, 0);
  211. }
  212. }
  213. }
  214. //修改
  215. //$where和$param的参数形式形同上面的函数sqlinsert的$param
  216. //@return 成功执行返回update操作影响的数量
  217. public function sqlupdate($table, $param, $where){
  218. if(!is_array($param)){
  219. throw new Exception('sqlupdate参数错误', 907);
  220. }
  221. $sql = 'update '.$table.' set ';
  222. $params = array();
  223. foreach($param as $key => $val){
  224. $params[] = $key.'='.$this->sql_check_input($val);
  225. }
  226. $params_str = implode(',', $params);
  227. $sql .= $params_str;
  228. $wheres = array();
  229. foreach($where as $key => $val){
  230. $wheres[] = $key.'='.$this->sql_check_input($val);
  231. }
  232. $wheres_str = implode(' and ', $wheres);
  233. $sql .= ' where '.$wheres_str;
  234. try {
  235. $num = $this->pdo->exec($sql);
  236. //2018/11/14记录SQL
  237. if($this->logSQL) {
  238. $this->log->debug($sql, 0);
  239. }
  240. return $num;//返回删除记录数
  241. } catch(PDOException $e) {
  242. $msg = $e->getMessage().'【错误的SQL语句:'.$sql.'】';
  243. if($this->debug) {
  244. echo $msg;
  245. }else{
  246. $this->log->debug($msg, 0);
  247. }
  248. }
  249. }
  250. //过滤数据,防止注入
  251. //$arr_val为数组,形如:array('string', 'abcdef')
  252. //第1个参数可接受的值为:number、string、expression
  253. public function sql_check_input($arr_val)
  254. {
  255. $value = $arr_val[1];
  256. if (get_magic_quotes_gpc())
  257. {
  258. $value = stripslashes($value);
  259. }
  260. // 如果是数字进行验证
  261. $type = $arr_val[0];
  262. if ($type == 'number'){
  263. $isint = preg_match('/^-?\d+$/', $value);
  264. $isfloat = preg_match('/^(-?\d+)(\.\d+)?$/', $value);
  265. if(!$isint && !$isfloat){
  266. throw new Exception('参数值'.$value.'应该为数字', 904);
  267. }
  268. }
  269. // 如果是字符串加引号
  270. if ($type == 'string'){
  271. $value = "'" . $this->sql_escape_mimic($value) . "'";
  272. }
  273. return $value;
  274. }
  275. //得到最后一条插入ID
  276. public function getLastId() {
  277. return $this->pdo->lastInsertId();
  278. }
  279. /**
  280. * sql_escape_mimic 用于在无mysql连接情况下替代mysql_real_escape_string的作用(防止SQL注入)
  281. *
  282. * @param mixed $str
  283. * @return
  284. */
  285. public function sql_escape_mimic($str) {
  286. if($str === '0' || $str === 0) return $str;//2016/10/10修正等于0的情况
  287. $str = strval($str);//2018/11/14修正数字当做字符传递时的情况
  288. if(!empty($str) && is_string($str)) {
  289. return str_replace(array('\\', "\0", "\n", "\r", "'", '"', "\x1a"), array('\\\\', '\\0', '\\n', '\\r', "\\'", '\\"', '\\Z'), $str);
  290. }
  291. }
  292. }
  293. ?>