Database.php 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. <?php
  2. namespace app\admin\controller\general;
  3. use addons\database\library\Backup;
  4. use app\common\controller\Backend;
  5. use think\Db;
  6. use think\Debug;
  7. use think\Exception;
  8. use think\exception\PDOException;
  9. use ZipArchive;
  10. /**
  11. * 数据库管理
  12. *
  13. * @icon fa fa-database
  14. * @remark 可在线进行一些简单的数据库表优化或修复,查看表结构和数据。也可以进行SQL语句的操作
  15. */
  16. class Database extends Backend
  17. {
  18. protected $noNeedRight = ['backuplist'];
  19. public function _initialize()
  20. {
  21. if (!config("app_debug")) {
  22. $this->error("数据库管理插件只允许在开发环境下使用");
  23. }
  24. return parent::_initialize();
  25. }
  26. /**
  27. * 查看
  28. */
  29. public function index()
  30. {
  31. $tables_data_length = $tables_index_length = $tables_free_length = $tables_data_count = 0;
  32. $tables = $list = [];
  33. $list = Db::query("SHOW TABLES");
  34. foreach ($list as $key => $row) {
  35. $tables[] = ['name' => reset($row), 'rows' => 0];
  36. }
  37. $data['tables'] = $tables;
  38. $data['saved_sql'] = [];
  39. $this->view->assign($data);
  40. return $this->view->fetch();
  41. }
  42. /**
  43. * SQL查询
  44. */
  45. public function query()
  46. {
  47. $do_action = $this->request->post('do_action');
  48. echo '<style type="text/css">
  49. xmp,body{margin:0;padding:0;line-height:18px;font-size:13px;font-family:"Helvetica Neue", Helvetica, Microsoft Yahei, Hiragino Sans GB, WenQuanYi Micro Hei, sans-serif;}
  50. hr{height:1px;margin:5px 1px;background:#e3e3e3;border:none;}
  51. </style>';
  52. if ($do_action == '') {
  53. exit(__('Invalid parameters'));
  54. }
  55. $tablename = $this->request->post("tablename/a", []);
  56. if (in_array($do_action, array('doquery', 'optimizeall', 'repairall'))) {
  57. $this->$do_action();
  58. } elseif (count($tablename) == 0) {
  59. exit(__('请选中表后再进行操作'));
  60. } else {
  61. foreach ($tablename as $table) {
  62. $this->$do_action($table);
  63. echo "<br />";
  64. }
  65. }
  66. }
  67. private function viewinfo($name)
  68. {
  69. $row = Db::query("SHOW CREATE TABLE `{$name}`");
  70. $row = array_values($row[0]);
  71. $info = $row[1];
  72. echo "<xmp>{$info};</xmp>";
  73. }
  74. private function viewdata($name = '')
  75. {
  76. $sqlquery = "SELECT * FROM `{$name}`";
  77. $this->doquery($sqlquery);
  78. }
  79. private function optimize($name = '')
  80. {
  81. if (Db::execute("OPTIMIZE TABLE `{$name}`")) {
  82. echo __('Optimize table %s done', $name);
  83. } else {
  84. echo __('Optimize table %s fail', $name);
  85. }
  86. }
  87. private function optimizeall($name = '')
  88. {
  89. $list = Db::query("SHOW TABLES");
  90. foreach ($list as $key => $row) {
  91. $name = reset($row);
  92. if (Db::execute("OPTIMIZE TABLE {$name}")) {
  93. echo __('Optimize table %s done', $name);
  94. } else {
  95. echo __('Optimize table %s fail', $name);
  96. }
  97. echo "<br />";
  98. }
  99. }
  100. private function repair($name = '')
  101. {
  102. if (Db::execute("REPAIR TABLE `{$name}`")) {
  103. echo __('Repair table %s done', $name);
  104. } else {
  105. echo __('Repair table %s fail', $name);
  106. }
  107. }
  108. private function repairall($name = '')
  109. {
  110. $list = Db::query("SHOW TABLES");
  111. foreach ($list as $key => $row) {
  112. $name = reset($row);
  113. if (Db::execute("REPAIR TABLE {$name}")) {
  114. echo __('Repair table %s done', $name);
  115. } else {
  116. echo __('Repair table %s fail', $name);
  117. }
  118. echo "<br />";
  119. }
  120. }
  121. private function doquery($sql = null)
  122. {
  123. $sqlquery = $sql ? $sql : $this->request->post('sqlquery');
  124. if ($sqlquery == '') {
  125. exit(__('SQL can not be empty'));
  126. }
  127. $sqlquery = str_replace('__PREFIX__', config('database.prefix'), $sqlquery);
  128. $sqlquery = str_replace("\r", "", $sqlquery);
  129. $sqls = preg_split("/;[ \t]{0,}\n/i", $sqlquery);
  130. $maxreturn = 100;
  131. $r = '';
  132. foreach ($sqls as $key => $val) {
  133. if (trim($val) == '') {
  134. continue;
  135. }
  136. $val = rtrim($val, ';');
  137. $r .= "SQL:<span style='color:green;'>{$val}</span> ";
  138. if (preg_match("/^(select|explain)(.*)/i ", $val)) {
  139. Debug::remark("begin");
  140. $limit = stripos(strtolower($val), "limit") !== false ? true : false;
  141. try {
  142. $count = Db::execute($val);
  143. if ($count > 0) {
  144. $resultlist = Db::query($val . (!$limit && $count > $maxreturn ? ' LIMIT ' . $maxreturn : ''));
  145. } else {
  146. $resultlist = [];
  147. }
  148. } catch (\PDOException $e) {
  149. continue;
  150. }
  151. Debug::remark("end");
  152. $time = Debug::getRangeTime('begin', 'end', 4);
  153. $usedseconds = __('Query took %s seconds', $time) . "<br />";
  154. if ($count <= 0) {
  155. $r .= __('Query returned an empty result');
  156. } else {
  157. $r .= (__('Total:%s', $count) . (!$limit && $count > $maxreturn ? ',' . __('Max output:%s', $maxreturn) : ""));
  158. }
  159. $r = $r . ',' . $usedseconds;
  160. $j = 0;
  161. foreach ($resultlist as $m => $n) {
  162. $j++;
  163. if (!$limit && $j > $maxreturn) {
  164. break;
  165. }
  166. $r .= "<hr/>";
  167. $r .= "<font color='red'>" . __('Row:%s', $j) . "</font><br />";
  168. foreach ($n as $k => $v) {
  169. $r = $r . "<font color='blue'>" . htmlentities($k) . ":</font>" . htmlentities($v) . "<br/>\r\n";
  170. }
  171. }
  172. } else {
  173. try {
  174. Debug::remark("begin");
  175. $count = Db::getPdo()->exec($val);
  176. Debug::remark("end");
  177. } catch (\PDOException $e) {
  178. continue;
  179. }
  180. $time = Debug::getRangeTime('begin', 'end', 4);
  181. $r .= __('Query affected %s rows and took %s seconds', $count, $time) . "<br />";
  182. }
  183. }
  184. echo $r;
  185. }
  186. }