mypdo.class.php 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  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. // $this->dbconnect();
  62. }
  63. public function dbconnect($hostname, $username, $password, $database, $prefix) {
  64. $dsn = 'mysql:dbname='.$database.';host='.$hostname.';port=3306';
  65. try {
  66. $mypdo = new PDO($dsn, $username, $password);
  67. $mypdo -> query('set names utf8;');
  68. $mypdo -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  69. $this->pdo = $mypdo;
  70. $this->prefix = $prefix;
  71. // var_dump($this);
  72. return $this;
  73. } catch(PDOException $e) {
  74. if($this->debug) echo $e->getMessage();
  75. }
  76. }
  77. //数据库调试
  78. public function debug($level = 0){
  79. switch($level){
  80. case 0:
  81. $this->debug = false;
  82. $this->logSQL = false;
  83. break;
  84. case 1:
  85. $this->debug = true;
  86. $this->logSQL = false;
  87. break;
  88. case 2:
  89. $this->debug = true;
  90. $this->logSQL = true;
  91. break;
  92. }
  93. }
  94. //查询
  95. //本函数用于执行查询语句,增删改语句请使用其他专用函数
  96. //@return 查询结果集array()。
  97. //TODO: 禁止多条查询语句同时执行;禁止增删改语句通过这个函数执行。
  98. public function sqlQuery($sql){
  99. global $CountSQLSelect;
  100. try {
  101. //统计查询语句数量2016/6/16
  102. $sqlactstr = strtolower(substr($sql, 0, 6));
  103. if($sqlactstr == 'select') $CountSQLSelect++;
  104. $rs = $this -> pdo -> query($sql);
  105. $i = 0;
  106. $data = array();
  107. foreach($rs->fetchAll() as $result) {
  108. $data[$i] = $result;
  109. $i++;
  110. }
  111. $rs->closeCursor();
  112. //2018/11/14记录SQL
  113. if($this->logSQL) {
  114. $this->log->debug($sql, 0);
  115. }
  116. return $data;
  117. } catch(PDOException $e) {
  118. $msg = $e->getMessage().'【错误的SQL语句:'.$sql.'】';
  119. if($this->debug) {
  120. echo $msg;
  121. }else{
  122. $this->log->debug($msg, 0);
  123. }
  124. }
  125. }
  126. /***
  127. * @param $sql
  128. * @return mixed
  129. * 执行sql
  130. */
  131. public function execSql($sql)
  132. {
  133. try {
  134. $mypdo = new MyPdo();//这里框架中的pdo不能用
  135. $mypdo->exec($sql);//2018/11/14记录SQL
  136. if($this->logSQL) {
  137. $this->log->debug($sql, 0);
  138. }
  139. return $this->getLastId();
  140. } catch(PDOException $e) {
  141. $msg = $e->getMessage().'【错误的SQL语句:'.$sql.'】';
  142. if($this->debug) {
  143. echo $msg;
  144. }else{
  145. $this->log->debug($msg, 0);
  146. }
  147. }
  148. }
  149. //插入
  150. //@param $param可选值
  151. // string--表示字符串;
  152. // number--表示数字
  153. // expression--表达式
  154. //@return 成功执行返回刚插入的ID;
  155. public function sqlinsert($table, $param){
  156. if(!is_array($param)){
  157. throw new Exception('sqlinsert参数错误', 905);
  158. }
  159. $sql = 'insert into '.$table.'(';
  160. $keys = array_keys($param);
  161. $keys_str = implode(',', $keys);
  162. $sql .= $keys_str.') values(';
  163. $params = array();
  164. foreach($param as $val){
  165. $params[] = $this->sql_check_input($val);
  166. }
  167. $params_str = implode(',', $params);
  168. $sql .= $params_str.')';
  169. //var_dump($sql);
  170. try {
  171. $this->pdo->exec($sql);
  172. //2018/11/14记录SQL
  173. if($this->logSQL) {
  174. $this->log->debug($sql, 0);
  175. }
  176. return $this->getLastId();
  177. } catch(PDOException $e) {
  178. $msg = $e->getMessage().'【错误的SQL语句:'.$sql.'】';
  179. if($this->debug) {
  180. echo $msg;
  181. }else{
  182. $this->log->debug($msg, 0);
  183. }
  184. }
  185. }
  186. //删除
  187. //$where的参数形式形同上面的函数sqlinsert的$param
  188. //@return 成功执行返回delete操作影响的数量
  189. public function sqldelete($table, $where){
  190. if(!is_array($where)){
  191. throw new Exception('sqldelete参数错误', 906);
  192. }
  193. $sql = 'delete from '.$table.' where ';
  194. $wheres = array();
  195. foreach($where as $key => $val){
  196. $wheres[] = $key.'='.$this->sql_check_input($val);
  197. }
  198. $wheres_str = implode(' and ', $wheres);
  199. $sql .= $wheres_str;
  200. try {
  201. $num = $this->pdo->exec($sql);
  202. //2018/11/14记录SQL
  203. if($this->logSQL) {
  204. $this->log->debug($sql, 0);
  205. }
  206. return $num;//返回删除记录数
  207. } catch(PDOException $e) {
  208. $msg = $e->getMessage().'【错误的SQL语句:'.$sql.'】';
  209. if($this->debug) {
  210. echo $msg;
  211. }else{
  212. $this->log->debug($msg, 0);
  213. }
  214. }
  215. }
  216. //修改
  217. //$where和$param的参数形式形同上面的函数sqlinsert的$param
  218. //@return 成功执行返回update操作影响的数量
  219. public function sqlupdate($table, $param, $where){
  220. if(!is_array($param)){
  221. throw new Exception('sqlupdate参数错误', 907);
  222. }
  223. $sql = 'update '.$table.' set ';
  224. $params = array();
  225. foreach($param as $key => $val){
  226. $params[] = $key.'='.$this->sql_check_input($val);
  227. }
  228. $params_str = implode(',', $params);
  229. $sql .= $params_str;
  230. $wheres = array();
  231. foreach($where as $key => $val){
  232. $wheres[] = $key.'='.$this->sql_check_input($val);
  233. }
  234. $wheres_str = implode(' and ', $wheres);
  235. $sql .= ' where '.$wheres_str;
  236. try {
  237. $num = $this->pdo->exec($sql);
  238. //2018/11/14记录SQL
  239. if($this->logSQL) {
  240. $this->log->debug($sql, 0);
  241. }
  242. return $num;//返回删除记录数
  243. } catch(PDOException $e) {
  244. $msg = $e->getMessage().'【错误的SQL语句:'.$sql.'】';
  245. if($this->debug) {
  246. echo $msg;
  247. }else{
  248. $this->log->debug($msg, 0);
  249. }
  250. }
  251. }
  252. //过滤数据,防止注入
  253. //$arr_val为数组,形如:array('string', 'abcdef')
  254. //第1个参数可接受的值为:number、string、expression
  255. public function sql_check_input($arr_val)
  256. {
  257. $value = $arr_val[1];
  258. if (get_magic_quotes_gpc())
  259. {
  260. $value = stripslashes($value);
  261. }
  262. // 如果是数字进行验证
  263. $type = $arr_val[0];
  264. if ($type == 'number'){
  265. $isint = preg_match('/^-?\d+$/', $value);
  266. $isfloat = preg_match('/^(-?\d+)(\.\d+)?$/', $value);
  267. if(!$isint && !$isfloat){
  268. throw new Exception('参数值'.$value.'应该为数字', 904);
  269. }
  270. }
  271. // 如果是字符串加引号
  272. if ($type == 'string'){
  273. $value = "'" . $this->sql_escape_mimic($value) . "'";
  274. }
  275. return $value;
  276. }
  277. //得到最后一条插入ID
  278. public function getLastId() {
  279. return $this->pdo->lastInsertId();
  280. }
  281. /**
  282. * sql_escape_mimic 用于在无mysql连接情况下替代mysql_real_escape_string的作用(防止SQL注入)
  283. *
  284. * @param mixed $str
  285. * @return
  286. */
  287. public function sql_escape_mimic($str) {
  288. if($str === '0' || $str === 0) return $str;//2016/10/10修正等于0的情况
  289. $str = strval($str);//2018/11/14修正数字当做字符传递时的情况
  290. if(!empty($str) && is_string($str)) {
  291. return str_replace(array('\\', "\0", "\n", "\r", "'", '"', "\x1a"), array('\\\\', '\\0', '\\n', '\\r', "\\'", '\\"', '\\Z'), $str);
  292. }
  293. }
  294. }
  295. ?>