Pdo.php 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. <?php namespace Dever\Store;
  2. use Dever;
  3. use Dever\Debug;
  4. use Dever\Sql;
  5. class Pdo extends Base
  6. {
  7. protected $tool;
  8. protected function connect($setting)
  9. {
  10. $this->tool = Dever::get(Sql::class);
  11. $this->type = $setting['type'];
  12. $handle = false;
  13. if (strpos($setting['host'], ':') !== false) {
  14. list($setting['host'], $setting['port']) = explode(':', $setting['host']);
  15. }
  16. if (empty($setting['pdo_type'])) {
  17. $setting['pdo_type'] = 'mysql';
  18. }
  19. if (empty($setting['charset'])) {
  20. $setting['charset'] = 'utf8mb4';
  21. }
  22. if (empty($setting['collation'])) {
  23. $setting['collation'] = 'utf8mb4_general_ci';
  24. }
  25. $dsn = $setting['pdo_type'] . ':type='.$setting['type'].';host='.$setting['host'].';port='.$setting['port'].';dbname='.$setting['name'].';collation='.$setting['collation'];
  26. try {
  27. if (empty($setting['persistent'])) {
  28. $persistent = false;
  29. }
  30. $handle = new \PDO($dsn, $setting['user'], $setting['pwd'], [\PDO::ATTR_PERSISTENT => $persistent]);
  31. $handle->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
  32. $handle->setAttribute(\PDO::ATTR_CASE, \PDO::CASE_NATURAL);
  33. $handle->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_ASSOC);
  34. $handle->setAttribute(\PDO::ATTR_STRINGIFY_FETCHES, false);
  35. $handle->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
  36. //$handle->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
  37. //handle->setAttribute(\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
  38. Dever::debug('db ' . $setting['host'] . ' connected', $setting['type']);
  39. return $handle;
  40. } catch (\PDOException $e) {
  41. if (strstr($e->getMessage(), 'Unknown database')) {
  42. $this->create($setting);
  43. return $this->connect($setting);
  44. } else {
  45. Dever::out()->error($e->getMessage());
  46. }
  47. }
  48. }
  49. private function create($setting)
  50. {
  51. $method = 'mysql';
  52. if (function_exists('mysqli_connect')) {
  53. $method = 'mysqli';
  54. }
  55. $connect = $method . '_connect';
  56. $query = $method . '_query';
  57. $close = $method . '_close';
  58. $link = $connect($setting['host'] . ':' . $setting['port'], $setting['user'], $setting['pwd']);
  59. if ($link) {
  60. $sql = 'CREATE DATABASE `' . $setting['name'] . '` DEFAULT CHARACTER SET ' . $setting['charset'] . ' COLLATE ' . $setting['collation'];
  61. if ($method == 'mysql') {
  62. $query($sql, $link);
  63. } else {
  64. $query($link, $sql);
  65. }
  66. $close($link);
  67. }
  68. }
  69. public function struct($config, $state = 0)
  70. {
  71. if ($state) {
  72. $sql = $this->tool->alter($config['table'], $config['struct'], $this->query($this->tool->desc($config['table'])));
  73. if ($sql) {
  74. $this->query($sql);
  75. }
  76. } else {
  77. $this->query($this->tool->create($config));
  78. }
  79. if (isset($config['default']) && $config['default']) {
  80. $count = $this->count($config['table'], [], $config['struct']);
  81. if (!$count) {
  82. $this->query($this->tool->inserts($config['table'], $config['default']));
  83. }
  84. }
  85. }
  86. public function index($config, $state = 0)
  87. {
  88. $this->query($this->tool->index($config['table'], $config['index'], $this->query($this->tool->showIndex($config['table']))));
  89. }
  90. public function partition($config, $partition)
  91. {
  92. $this->query($this->tool->partition($config['table'], $partition, $this->query($this->tool->showIndex($config['table']))));
  93. }
  94. public function query($sql, $bind = [], $method = 'read')
  95. {
  96. try {
  97. if ($bind) {
  98. $handle = $this->$method->prepare($sql);
  99. $handle->execute($bind);
  100. } else {
  101. if (strpos($sql, ';')) {
  102. $this->$method->setAttribute(\PDO::ATTR_STRINGIFY_FETCHES, true);
  103. $this->$method->setAttribute(\PDO::ATTR_EMULATE_PREPARES, true);
  104. }
  105. $handle = $this->$method->query($sql);
  106. }
  107. } catch (\PDOException $exception) {
  108. $this->error(array('sql' => $sql, 'msg' => $exception->getMessage()));
  109. }
  110. if (Dever::get(Debug::class)->shell) {
  111. $this->bsql($sql, $bind);
  112. $this->log(array('sql' => $sql, 'count' => $handle->rowCount()));
  113. }
  114. return $handle;
  115. }
  116. public function load($table, $param, $set, $field, $version)
  117. {
  118. $bind = [];
  119. $sql = $this->tool->select($table, $param, $bind, $set, $field, $version);
  120. return $this->query($sql, $bind);
  121. }
  122. public function sql($table, $param, $set, $field, $version)
  123. {
  124. $bind = '';
  125. return $this->tool->select($table, $param, $bind, $set, $field, $version);
  126. }
  127. public function select($table, $param, $set, $field, $version)
  128. {
  129. return $this->load($table, $param, $set, $field, $version)->fetchAll();
  130. }
  131. public function find($table, $param, $set, $field, $version)
  132. {
  133. return $this->load($table, $param, $set, $field, $version)->fetch();
  134. }
  135. public function column($table, $param, $set, $field, $version)
  136. {
  137. return $this->load($table, $param, $set, $field, $version)->fetchColumn();
  138. }
  139. public function columns($table, $param, $set, $field, $version)
  140. {
  141. return $this->load($table, $param, $set, $field, $version)->fetchAll(\PDO::FETCH_COLUMN);
  142. }
  143. public function count($table, $param, $field)
  144. {
  145. return $this->load($table, $param, array('col'=>'count(*)'), $field, false)->fetch(\PDO::FETCH_NUM)[0];
  146. }
  147. public function explain($table, $param, $field)
  148. {
  149. $bind = [];
  150. $sql = $this->tool->explain($this->tool->select($table, $param, $bind, array('col'=>'count(*)'), $field, false));
  151. return $this->query($sql, $bind)->fetch();
  152. }
  153. public function insert($table, $data, $field)
  154. {
  155. $bind = [];
  156. $sql = $this->tool->insert($table, $data, $bind, $field);
  157. $this->query($sql, $bind, 'update');
  158. return $this->update->lastInsertId();
  159. }
  160. public function inserts($table, $data, $field)
  161. {
  162. $sql = $this->tool->inserts($table, $data);
  163. $this->query($sql, [], 'update');
  164. return $this->update->lastInsertId();
  165. }
  166. public function update($table, $param, $data, $field)
  167. {
  168. $bind = [];
  169. $sql = $this->tool->update($table, $param, $data, $bind, $field);
  170. return $this->query($sql, $bind, 'update')->rowCount();
  171. }
  172. public function delete($table, $param, $field)
  173. {
  174. $bind = [];
  175. $sql = $this->tool->delete($table, $param, $bind, $field);
  176. return $this->query($sql, $bind, 'update')->rowCount();
  177. }
  178. public function copy($table, $dest, $param, $field)
  179. {
  180. $bind = [];
  181. $sql = $this->tool->copy($table, $dest, $param, $bind, $field);
  182. return $this->query($sql, $bind, 'update')->rowCount();
  183. }
  184. public function optimize($table)
  185. {
  186. $sql = $this->tool->optimize($table) . ';' . $this->tool->analyze($table);
  187. return $this->query($sql, [], 'update');
  188. }
  189. public function inTransaction()
  190. {
  191. return $this->update->inTransaction();
  192. }
  193. public function begin()
  194. {
  195. $this->update->beginTransaction();
  196. }
  197. public function commit()
  198. {
  199. $this->update->commit();
  200. }
  201. public function rollback()
  202. {
  203. $this->update->rollback();
  204. }
  205. public function transaction($class, $param, $msg)
  206. {
  207. if (Dever::getCommit()) {
  208. try {
  209. Dever::setCommit();
  210. $this->begin();
  211. $result = call_user_func_array($class, $param);
  212. $this->commit();
  213. return $result;
  214. } catch (\Exception $e) {
  215. $this->rollback();
  216. Dever::out()->error($msg);
  217. }
  218. } else {
  219. return call_user_func_array($class, $param);
  220. }
  221. }
  222. }