Baksql.php 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. <?php
  2. /**
  3. * 备份数据库的扩展类
  4. */
  5. namespace org;
  6. use think\Db;
  7. use think\Config;
  8. class Baksql {
  9. private $config=[];
  10. private $handler;
  11. private $tables = array();//需要备份的表
  12. private $begin; //开始时间
  13. private $error;//错误信息
  14. public function __construct($config,$folder,$version) {
  15. //保存数据库文件路径
  16. $config['path'] = $folder.'/';
  17. //数据库文件名称
  18. $config["sqlbakname"] = $version.'.sql';
  19. $this->config = $config;
  20. $this->begin = microtime(true);
  21. header("Content-type: text/html;charset=utf-8");
  22. $this->connect();
  23. }
  24. //
  25. private function connect() {
  26. $this->handler = Db::connect();
  27. }
  28. /**
  29. * 查询
  30. * @param string $sql
  31. * @return mixed
  32. */
  33. private function query($sql = '')
  34. {
  35. $list = $this->handler->query($sql);
  36. return $list;
  37. }
  38. /**
  39. * 获取全部表
  40. * @param string $dbName
  41. * @return array
  42. */
  43. private function get_dbname($dbName = '*') {
  44. $sql = 'SHOW TABLES';
  45. $list = $this->query($sql);
  46. $tables = array();
  47. foreach ($list as $value)
  48. {
  49. $tables[] = $value['Tables_in_'.\think\facade\Config::get('database.database')];
  50. }
  51. return $tables;
  52. }
  53. /**
  54. * 获取表定义语句
  55. * @param string $table
  56. * @return mixed
  57. */
  58. private function get_dbhead($table = '')
  59. {
  60. $sql = "SHOW CREATE TABLE `".$table."`";
  61. $ddl = $this->query($sql)[0]['Create Table'] . ';';
  62. return $ddl;
  63. }
  64. /**
  65. * 获取表数据
  66. * @param string $table
  67. * @return mixed
  68. */
  69. private function get_dbdata($table = '')
  70. {
  71. $sql = "SHOW COLUMNS FROM `".$table."`";
  72. $list = $this->query($sql);
  73. //字段
  74. $columns = '';
  75. //需要返回的SQL
  76. $query = '';
  77. foreach ($list as $value)
  78. {
  79. $columns .= "`".$value['Field']."`,";
  80. }
  81. $columns = substr($columns, 0, -1);
  82. $data = $this->query("SELECT * FROM `".$table."`");
  83. foreach ($data as $value)
  84. {
  85. $dataSql = '';
  86. foreach ($value as $v)
  87. {
  88. $dataSql .= "'".$v."',";
  89. }
  90. $dataSql = substr($dataSql, 0, -1);
  91. $query .= "INSERT INTO `".$table."` ({$columns}) VALUES ({$dataSql});\r\n";
  92. }
  93. return $query;
  94. }
  95. /**
  96. * 写入文件
  97. * @param array $tables
  98. * @param array $ddl
  99. * @param array $data
  100. */
  101. private function writeToFile($tables = array(), $ddl = array(), $data = array())
  102. {
  103. $str = "/*\r\nMySQL Database Backup Tools\r\n";
  104. $str .= "Server:{$this->config['hostname']}:{$this->config['hostport']}\r\n";
  105. $str .= "Database:{$this->config['database']}\r\n";
  106. $str .= "Data:" . date('Y-m-d H:i:s', time()) . "\r\n*/\r\n";
  107. $str .= "SET FOREIGN_KEY_CHECKS=0;\r\n";
  108. $i = 0;
  109. foreach ($tables as $table)
  110. {
  111. $str .= "-- ----------------------------\r\n";
  112. $str .= "-- Table structure for {$table}\r\n";
  113. $str .= "-- ----------------------------\r\n";
  114. $str .= "DROP TABLE IF EXISTS `{$table}`;\r\n";
  115. $str .= $ddl[$i] . "\r\n";
  116. $str .= "-- ----------------------------\r\n";
  117. $str .= "-- Records of {$table}\r\n";
  118. $str .= "-- ----------------------------\r\n";
  119. $str .= $data[$i] . "\r\n";
  120. $i++;
  121. }
  122. if(!file_exists($this->config['path'])){mkdir($this->config['path']);}
  123. return file_put_contents($this->config['path'].$this->config['sqlbakname'], $str) ? true : false;
  124. }
  125. /**
  126. * 设置要备份的表
  127. * @param array $tables
  128. */
  129. private function setTables($tables = array())
  130. {
  131. if (!empty($tables) && is_array($tables))
  132. {
  133. //备份指定表
  134. $this->tables = $tables;
  135. }
  136. else
  137. {
  138. //备份全部表
  139. $this->tables = $this->get_dbname();
  140. }
  141. }
  142. /**
  143. * 备份
  144. * @param array $tables
  145. * @return bool
  146. */
  147. public function backup($tables = array())
  148. {
  149. //存储表定义语句的数组
  150. $ddl = array();
  151. //存储数据的数组
  152. $data = array();
  153. $this->setTables($tables);
  154. if (!empty($this->tables))
  155. {
  156. foreach ($this->tables as $table)
  157. {
  158. $ddl[] = $this->get_dbhead($table);
  159. $data[] = $this->get_dbdata($table);
  160. }
  161. //开始写入
  162. return $this->writeToFile($this->tables, $ddl, $data);
  163. }
  164. else
  165. {
  166. $this->error = '数据库中没有表!';
  167. return false;
  168. }
  169. }
  170. /**
  171. * 错误信息
  172. * @return mixed
  173. */
  174. public function getError()
  175. {
  176. return $this->error;
  177. }
  178. public function restore($filename = '')
  179. {
  180. $path=$this->config['path'].$filename;
  181. if (!file_exists($path))
  182. {
  183. $this->error('SQL文件不存在!');
  184. return false;
  185. }
  186. else
  187. {
  188. $sql = $this->parseSQL($path);
  189. //dump($sql);die;
  190. try
  191. {
  192. $this->handler->exec($sql);
  193. echo '还原成功!花费时间', round(microtime(true) - $this->begin,2) . 'ms';
  194. }
  195. catch (PDOException $e)
  196. {
  197. $this->error = $e->getMessage();
  198. return false;
  199. }
  200. }
  201. }
  202. /**
  203. * 解析SQL文件为SQL语句数组
  204. * @param string $path
  205. * @return array|mixed|string
  206. */
  207. private function parseSQL($path = '')
  208. {
  209. $sql = file_get_contents($path);
  210. $sql = explode("\r\n", $sql);
  211. //先消除--注释
  212. $sql = array_filter($sql, function ($data)
  213. {
  214. if (empty($data) || preg_match('/^--.*/', $data))
  215. {
  216. return false;
  217. }
  218. else
  219. {
  220. return true;
  221. }
  222. });
  223. $sql = implode('', $sql);
  224. //删除/**/注释
  225. $sql = preg_replace('/\/\*.*\*\//', '', $sql);
  226. return $sql;
  227. }
  228. /**
  229. * 下载备份
  230. * @param string $fileName
  231. * @return array|mixed|string
  232. */
  233. public function downloadFile($fileName) {
  234. $fileName=$this->config['path'].$fileName;
  235. if (file_exists($fileName)){
  236. ob_end_clean();
  237. header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
  238. header('Content-Description: File Transfer');
  239. header('Content-Type: application/octet-stream');
  240. header('Content-Length: ' . filesize($fileName));
  241. header('Content-Disposition: attachment; filename=' . basename($fileName));
  242. readfile($fileName);
  243. }else{
  244. $this->error="文件有错误!";
  245. }
  246. }
  247. /**
  248. * 获取文件是时间
  249. * @param string $file
  250. * @return string
  251. */
  252. private function getfiletime($file){
  253. $path=$this->config['path'].$file;
  254. $a = filemtime($path);
  255. $time = date("Y-m-d H:i:s", $a);
  256. return $time;
  257. }
  258. /**
  259. * 获取文件是大小
  260. * @param string $file
  261. * @return string
  262. */
  263. private function getfilesize($file){
  264. $perms=stat($this->config['path'].$file);
  265. $size = $perms['size'];
  266. $a = ['B', 'KB', 'MB', 'GB', 'TB'];
  267. $pos = 0;
  268. while ($size >= 1024) {
  269. $size /= 1024;
  270. $pos++;
  271. }
  272. return round($size, 2). $a[$pos];
  273. }
  274. /**
  275. * 获取文件列表
  276. * @param string $Order 级别
  277. * @return array
  278. */
  279. public function get_filelist($Order = 0) {
  280. $FilePath=$this->config['path'];
  281. // print_r($FilePath);die;
  282. $FilePath = opendir($FilePath);
  283. // $FilePath = scandir($FilePath);
  284. $FileAndFolderAyy=array();
  285. $i=1;
  286. while (false !== ($filename = readdir($FilePath))) {
  287. if ($filename!="." && $filename!=".."){
  288. $i++;
  289. $FileAndFolderAyy[$i]['name'] = $filename;
  290. $FileAndFolderAyy[$i]['time'] = $this->getfiletime($filename);
  291. $FileAndFolderAyy[$i]['size'] = $this->getfilesize($filename);
  292. }
  293. }
  294. $Order == 0 ? sort($FileAndFolderAyy) : rsort($FileAndFolderAyy);
  295. return $FileAndFolderAyy;
  296. }
  297. public function delfilename($filename){
  298. $path=$this->config['path'].$filename;
  299. if (@unlink($path)) {return '删除成功';}
  300. }
  301. }
  302. ?>