心理咨询网
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

Mysqli.php 8.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. <?php
  2. /**
  3. * @copyright (C)2016-2099 Hnaoyun Inc.
  4. * @author XingMeng
  5. * @email hnxsh@foxmail.com
  6. * @date 2016年11月6日
  7. * 数据库mysqli驱动
  8. */
  9. namespace core\database;
  10. use core\basic\Config;
  11. class Mysqli implements Builder
  12. {
  13. protected static $mysqli;
  14. protected $master;
  15. protected $slave;
  16. protected $begin = false;
  17. private function __construct()
  18. {}
  19. public function __destruct()
  20. {
  21. if ($this->begin) { // 存在待提交的事务时自动进行提交
  22. $this->commit();
  23. }
  24. }
  25. // 获取单一实例,使用单一实例数据库连接类
  26. public static function getInstance()
  27. {
  28. if (! self::$mysqli) {
  29. self::$mysqli = new self();
  30. }
  31. return self::$mysqli;
  32. }
  33. // 连接数据库,接受数据库连接参数,返回数据库连接对象
  34. public function conn($cfg)
  35. {
  36. if (! extension_loaded('mysqli')) {
  37. if (extension_loaded('pdo_mysql')) {
  38. error('未检测到您服务器环境的mysqli数据库扩展,请检查php.ini中是否已经开启该扩展!<br>另外,检测到您服务器支持pdo_mysql扩展,您也可以修改数据库配置连接驱动为pdo_mysql试试!');
  39. } else {
  40. error('未检测到您服务器环境的mysqli数据库扩展,请检查php.ini中是否已经开启该扩展!');
  41. }
  42. }
  43. // 优化>php5.3版本 在win2008以上服务器连接
  44. if ($cfg['host'] == 'localhost') {
  45. $cfg['host'] = '127.0.0.1';
  46. }
  47. $conn = @new \Mysqli($cfg['host'], $cfg['user'], $cfg['passwd'], $cfg['dbname'], $cfg['port']);
  48. if (mysqli_connect_errno()) {
  49. error("连接数据库服务器失败:" . iconv('gbk', 'utf-8', mysqli_connect_error()));
  50. }
  51. $charset = Config::get('database.charset') ?: 'utf8';
  52. $conn->set_charset($charset); // 设置编码
  53. return $conn;
  54. }
  55. // 关闭自动提交,开启事务模式
  56. public function begin()
  57. {
  58. $this->master->autocommit(false);
  59. $this->begin = true;
  60. }
  61. // 提交事务
  62. public function commit()
  63. {
  64. $this->master->commit(); // 提交事务
  65. $this->master->autocommit(true); // 提交后恢复自动提交
  66. $this->begin = false; // 关闭事务模式
  67. }
  68. // 执行SQL语句,接受完整SQL语句,返回结果集对象
  69. public function query($sql, $type = 'master')
  70. {
  71. $time_s = microtime(true);
  72. switch ($type) {
  73. case 'master':
  74. if (! $this->master) {
  75. $cfg = Config::get('database');
  76. $this->master = $this->conn($cfg);
  77. $this->master->query("SET sql_mode='NO_ENGINE_SUBSTITUTION'"); // 写入规避严格模式
  78. }
  79. if (Config::get('database.transaction') && ! $this->begin) { // 根据配置开启mysql事务,注意需要是InnoDB引擎
  80. $this->begin();
  81. }
  82. $result = $this->master->query($sql) or $this->error($sql, 'master');
  83. break;
  84. case 'slave':
  85. if (! $this->slave) {
  86. // 未设置从服务器时直接读取主数据库配置
  87. if (! $cfg = Config::get('database.slave')) {
  88. $cfg = Config::get('database');
  89. } else {
  90. // 随机选择从数据库
  91. if (is_multi_array($cfg)) {
  92. $count = count($cfg);
  93. $cfg = $cfg['slave' . mt_rand(1, $count)];
  94. }
  95. }
  96. $this->slave = $this->conn($cfg);
  97. }
  98. $result = $this->slave->query($sql) or $this->error($sql, 'slave');
  99. break;
  100. }
  101. return $result;
  102. }
  103. // 数据是否存在模型,接受完整SQL语句,返回boolean数据
  104. public function isExist($sql)
  105. {
  106. $result = $this->query($sql, 'slave');
  107. if ($result->num_rows) {
  108. $result->free();
  109. return true;
  110. } else {
  111. return false;
  112. }
  113. }
  114. // 获取记录总量模型,接受数据库表名,返回int数据
  115. public function rows($table)
  116. {
  117. $sql = "SELECT count(*) FROM $table";
  118. $result = $this->query($sql, 'slave');
  119. if (! ! $row = $result->fetch_array(2)) {
  120. $result->free();
  121. return $row[0];
  122. } else {
  123. return 0;
  124. }
  125. }
  126. // 读取字段数量模型,接受数据库表名,返回int数据
  127. public function fields($table)
  128. {
  129. $sql = "SELECT * FROM $table LIMIT 1";
  130. $result = $this->query($sql, 'slave');
  131. if ($result) {
  132. return $result->field_count;
  133. } else {
  134. return 0;
  135. }
  136. }
  137. /**
  138. * 获取表信息,接受数据库表名,返回表字段信息数组
  139. *
  140. * @param $table 表名
  141. */
  142. public function tableFields($table)
  143. {
  144. $sql = "describe $table";
  145. $result = $this->query($sql, 'slave');
  146. $rows = array();
  147. if ($this->slave->affected_rows) {
  148. while (! ! $row = $result->fetch_object()) {
  149. $rows[] = $row->Field;
  150. }
  151. $result->free();
  152. }
  153. return $rows;
  154. }
  155. /**
  156. * 查询一条数据模型,接受完整SQL语句,有数据返回对象数组,否则空数组
  157. *
  158. * @$type 可以是MYSQLI_ASSOC ,MYSQLI_NUM ,MYSQLI_BOTH,不设置则返回对象数组
  159. */
  160. public function one($sql, $type = null)
  161. {
  162. $result = $this->query($sql, 'slave');
  163. $row = array();
  164. if ($this->slave->affected_rows) {
  165. if ($type) {
  166. $row = $result->fetch_array($type);
  167. } else {
  168. $row = $result->fetch_object();
  169. }
  170. $result->free();
  171. }
  172. return $row;
  173. }
  174. /**
  175. * 查询多条数据模型,接受完整SQL语句,有数据返回二维对象数组,否则空数组
  176. * @$type 可以是MYSQLI_ASSOC ,MYSQLI_NUM ,MYSQLI_BOTH,不设置则返回对象模式
  177. */
  178. public function all($sql, $type = null)
  179. {
  180. $result = $this->query($sql, 'slave');
  181. $rows = array();
  182. if ($this->slave->affected_rows) {
  183. if ($type) {
  184. while (! ! $array = $result->fetch_array($type)) { // 关联数组或数字数组或同时
  185. $rows[] = $array;
  186. }
  187. } else {
  188. while (! ! $objects = $result->fetch_object()) {
  189. $rows[] = $objects;
  190. }
  191. }
  192. $result->free();
  193. }
  194. return $rows;
  195. }
  196. // 数据增、删、改模型,接受完整SQL语句,返回影响的行数的int数据
  197. public function amd($sql)
  198. {
  199. $result = $this->query($sql, 'master');
  200. $num = $this->master->affected_rows;
  201. if ($num > 0) {
  202. return $num;
  203. } else {
  204. return 0;
  205. }
  206. }
  207. // 最近一次插入数据的自增字段值,返回int数据
  208. public function insertId()
  209. {
  210. return $this->master->insert_id;
  211. }
  212. // 执行多条SQL模型,成功返回true,否则false
  213. public function multi($sql)
  214. {
  215. $result = $this->master->multi_query($sql) or $this->error($sql);
  216. if ($result) {
  217. $result->free();
  218. return true;
  219. } else {
  220. return false;
  221. }
  222. }
  223. // 显示执行错误
  224. protected function error($sql, $conn)
  225. {
  226. $err = '错误:' . mysqli_error($this->$conn);
  227. if (preg_match('/XPATH/i', $err)) {
  228. $err = '';
  229. }
  230. if ($this->begin) { // 如果是事务模式,发生错误,则回滚
  231. $this->$conn->rollback();
  232. $this->begin = false;
  233. }
  234. // error('执行SQL发生错误!' . $err . '语句:' . $sql);
  235. error('执行SQL发生错误!' . $err);
  236. }
  237. //返回对象结果集
  238. public function fetchQuery($obj){
  239. return $obj->fetch_all();
  240. }
  241. }