111
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 
 

226 linhas
6.3 KiB

  1. <?php
  2. /**
  3. * @copyright (C)2016-2099 Hnaoyun Inc.
  4. * @author XingMeng
  5. * @email hnxsh@foxmail.com
  6. * @date 2017年8月23日
  7. * 数据库Sqlite驱动 ,写入数据时自动启用事务
  8. */
  9. namespace core\database;
  10. use core\basic\Config;
  11. class Sqlite implements Builder
  12. {
  13. protected static $sqlite;
  14. protected $master;
  15. protected $slave;
  16. private $begin = false;
  17. private function __construct()
  18. {}
  19. public function __destruct()
  20. {
  21. if ($this->begin) { // 存在待提交的事务时自动进行提交
  22. $this->master->exec('commit;');
  23. }
  24. }
  25. // 获取单一实例,使用单一实例数据库连接类
  26. public static function getInstance()
  27. {
  28. if (! self::$sqlite) {
  29. self::$sqlite = new self();
  30. }
  31. return self::$sqlite;
  32. }
  33. // 连接数据库,接受数据库连接参数,返回数据库连接对象
  34. public function conn($cfg)
  35. {
  36. if (extension_loaded('SQLite3')) {
  37. try {
  38. $conn = new \SQLite3($cfg);
  39. $conn->busyTimeout(15 * 1000); // 设置繁忙延迟时间
  40. } catch (\Exception $e) {
  41. error("读取数据库文件失败:" . iconv('gbk', 'utf-8', $e->getMessage()));
  42. }
  43. } else {
  44. error('未检测到您服务器环境的SQLite3数据库扩展,请检查php.ini中是否已经开启该扩展!');
  45. }
  46. return $conn;
  47. }
  48. // 执行SQL语句,接受完整SQL语句,返回结果集对象
  49. public function query($sql, $type = 'master')
  50. {
  51. $time_s = microtime(true);
  52. if (! $this->master || ! $this->slave) {
  53. $cfg = ROOT_PATH . Config::get('database.dbname');
  54. $conn = $this->conn($cfg);
  55. $this->master = $conn;
  56. $this->slave = $conn;
  57. }
  58. switch ($type) {
  59. case 'master':
  60. if (! $this->begin) { // 存在写入时自动开启显式事务,提高写入性能
  61. $this->master->exec('begin;');
  62. $this->begin = true;
  63. }
  64. $result = $this->master->exec($sql) or $this->error($sql, 'master');
  65. break;
  66. case 'slave':
  67. $result = $this->slave->query($sql) or $this->error($sql, 'slave');
  68. break;
  69. }
  70. return $result;
  71. }
  72. // 数据是否存在模型,接受完整SQL语句,返回boolean数据
  73. public function isExist($sql)
  74. {
  75. $result = $this->query($sql, 'slave');
  76. if ($result->fetchArray()) {
  77. $result->finalize();
  78. return true;
  79. } else {
  80. return false;
  81. }
  82. }
  83. // 获取记录总量模型,接受数据库表名,返回int数据
  84. public function rows($table)
  85. {
  86. $sql = "SELECT count(*) FROM $table";
  87. $result = $this->query($sql, 'slave');
  88. if (! ! $row = $result->fetchArray(2)) {
  89. $result->finalize();
  90. return $row[0];
  91. } else {
  92. return 0;
  93. }
  94. }
  95. // 读取字段数量模型,接受数据库表名,返回int数据
  96. public function fields($table)
  97. {
  98. $sql = "SELECT * FROM $table LIMIT 1";
  99. $result = $this->query($sql, 'slave');
  100. if ($result) {
  101. return $result->numColumns();
  102. } else {
  103. return false;
  104. }
  105. }
  106. /**
  107. * 获取表字段,接受数据库表名,返回表字段数组
  108. *
  109. * @param $table 表名
  110. */
  111. public function tableFields($table)
  112. {
  113. $sql = "pragma table_info($table)";
  114. $result = $this->query($sql, 'slave');
  115. $rows = array();
  116. while (! ! $row = $result->fetchArray(SQLITE3_ASSOC)) {
  117. $rows[] = $row['name'];
  118. }
  119. $result->finalize();
  120. return $rows;
  121. }
  122. // 查询一条数据模型,接受完整SQL语句,有数据返回对象数组,否则空数组
  123. public function one($sql, $type = null)
  124. {
  125. if (! $type) {
  126. $my_type = SQLITE3_ASSOC;
  127. } else {
  128. $my_type = $type;
  129. }
  130. $row = array();
  131. $result = $this->query($sql, 'slave');
  132. if (! ! $row = $result->fetchArray($my_type)) {
  133. if (! $type && $row) {
  134. $out = new \stdClass();
  135. foreach ($row as $key => $value) {
  136. $out->$key = $value;
  137. }
  138. $row = $out;
  139. }
  140. $result->finalize();
  141. }
  142. return $row;
  143. }
  144. // 查询多条数据模型,接受完整SQL语句,有数据返回二维对象数组,否则空数组
  145. public function all($sql, $type = null)
  146. {
  147. if (! $type) {
  148. $my_type = SQLITE3_ASSOC;
  149. } else {
  150. $my_type = $type;
  151. }
  152. $result = $this->query($sql, 'slave');
  153. $rows = array();
  154. while (! ! $row = $result->fetchArray($my_type)) {
  155. if (! $type && $row) {
  156. $out = new \stdClass();
  157. foreach ($row as $key => $value) {
  158. $out->$key = $value;
  159. }
  160. $row = $out;
  161. }
  162. $rows[] = $row;
  163. }
  164. $result->finalize();
  165. return $rows;
  166. }
  167. // 数据增、删、改模型,接受完整SQL语句,返回影响的行数的int数据
  168. public function amd($sql)
  169. {
  170. $result = $this->query($sql, 'master');
  171. if ($result) {
  172. return $result;
  173. } else {
  174. return 0;
  175. }
  176. }
  177. // 最近一次插入数据的自增字段值,返回int数据
  178. public function insertId()
  179. {
  180. return $this->master->lastInsertRowID();
  181. }
  182. // 执行多条SQL模型,成功返回true,否则false
  183. public function multi($sql)
  184. {
  185. $sqls = explode(';', $sql);
  186. foreach ($sqls as $key => $value) {
  187. $result = $this->query($value, 'master');
  188. }
  189. if ($result) {
  190. return true;
  191. } else {
  192. return false;
  193. }
  194. }
  195. // 显示执行错误
  196. protected function error($sql, $conn)
  197. {
  198. $err = '错误:' . $this->$conn->lastErrorMsg() . ',';
  199. if ($this->begin) { // 存在显式开启事务时进行回滚
  200. $this->master->exec('rollback;');
  201. $this->begin = false;
  202. }
  203. error('执行SQL发生错误!' . $err . '语句:' . $sql);
  204. }
  205. }