Backup.php 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. <?php
  2. namespace addons\database\library;
  3. use Exception;
  4. use PDO;
  5. use ZipArchive;
  6. class Backup
  7. {
  8. private $host = '';
  9. private $user = '';
  10. private $name = '';
  11. private $pass = '';
  12. private $port = '';
  13. private $tables = ['*'];
  14. private $ignoreTables = [];
  15. private $db;
  16. private $ds = "\n";
  17. public function __construct($host = null, $user = null, $name = null, $pass = null, $port = 3306)
  18. {
  19. if ($host !== null) {
  20. $this->host = $host;
  21. $this->name = $name;
  22. $this->port = $port;
  23. $this->pass = $pass;
  24. $this->user = $user;
  25. }
  26. $this->db = new PDO('mysql:host=' . $this->host . ';dbname=' . $this->name . '; port=' . $port, $this->user, $this->pass, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
  27. $this->db->exec('SET NAMES "utf8"');
  28. }
  29. /**
  30. * 设置备份表
  31. * @param $table
  32. * @return $this
  33. */
  34. public function setTable($table)
  35. {
  36. if ($table) {
  37. $this->tables = is_array($table) ? $table : explode(',', $table);
  38. }
  39. return $this;
  40. }
  41. /**
  42. * 设置忽略备份的表
  43. * @param $table
  44. * @return $this
  45. */
  46. public function setIgnoreTable($table)
  47. {
  48. if ($table) {
  49. $this->ignoreTables = is_array($table) ? $table : explode(',', preg_replace('/\s+/', '', $table));
  50. }
  51. return $this;
  52. }
  53. public function backup($backUpdir = 'download/')
  54. {
  55. $sql = $this->_init();
  56. $zip = new ZipArchive();
  57. $date = date('YmdHis');
  58. if (!is_dir($backUpdir)) {
  59. @mkdir($backUpdir, 0755);
  60. }
  61. $name = "backup-{$this->name}-{$date}";
  62. $filename = $backUpdir . $name . ".zip";
  63. if ($zip->open($filename, ZIPARCHIVE::CREATE) !== true) {
  64. throw new Exception("Could not open <$filename>\n");
  65. }
  66. $zip->addFromString($name . ".sql", $sql);
  67. $zip->close();
  68. }
  69. private function _init()
  70. {
  71. # COUNT
  72. $ct = 0;
  73. # CONTENT
  74. $sqldump = '';
  75. # COPYRIGHT & OPTIONS
  76. $sqldump .= "-- SQL Dump by Erik Edgren\n";
  77. $sqldump .= "-- version 1.0\n";
  78. $sqldump .= "--\n";
  79. $sqldump .= "-- SQL Dump created: " . date('F jS, Y \@ g:i a') . "\n\n";
  80. $sqldump .= "SET SQL_MODE=\"NO_AUTO_VALUE_ON_ZERO\";";
  81. $sqldump .= "\n\n\n\n-- --------------------------------------------------------\n\n\n\n";
  82. $tables = $this->db->query("SHOW FULL TABLES WHERE Table_Type != 'VIEW'");
  83. # LOOP: Get the tables
  84. foreach ($tables AS $table) {
  85. // 忽略表
  86. if (in_array($table[0], $this->ignoreTables)) {
  87. continue;
  88. }
  89. # COUNT
  90. $ct++;
  91. /** ** ** ** ** **/
  92. # DATABASE: Count the rows in each tables
  93. $count_rows = $this->db->prepare("SELECT * FROM " . $table[0]);
  94. $count_rows->execute();
  95. $c_rows = $count_rows->columnCount();
  96. # DATABASE: Count the columns in each tables
  97. $count_columns = $this->db->prepare("SELECT COUNT(*) FROM " . $table[0]);
  98. $count_columns->execute();
  99. $c_columns = $count_columns->fetchColumn();
  100. /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/
  101. # MYSQL DUMP: Remove tables if they exists
  102. $sqldump .= "--\n";
  103. $sqldump .= "-- Remove the table if it exists\n";
  104. $sqldump .= "--\n\n";
  105. $sqldump .= "DROP TABLE IF EXISTS `" . $table[0] . "`;\n\n\n";
  106. /** ** ** ** ** **/
  107. # MYSQL DUMP: Create table if they do not exists
  108. $sqldump .= "--\n";
  109. $sqldump .= "-- Create the table if it not exists\n";
  110. $sqldump .= "--\n\n";
  111. # LOOP: Get the fields for the table
  112. foreach ($this->db->query("SHOW CREATE TABLE " . $table[0]) AS $field) {
  113. $sqldump .= str_replace('CREATE TABLE', 'CREATE TABLE IF NOT EXISTS', $field['Create Table']);
  114. }
  115. # MYSQL DUMP: New rows
  116. $sqldump .= ";\n\n\n";
  117. /** ** ** ** ** **/
  118. # CHECK: There are one or more columns
  119. if ($c_columns != 0) {
  120. # MYSQL DUMP: List the data for each table
  121. $sqldump .= "--\n";
  122. $sqldump .= "-- List the data for the table\n";
  123. $sqldump .= "--\n\n";
  124. # MYSQL DUMP: Insert into each table
  125. $sqldump .= "INSERT INTO `" . $table[0] . "` (";
  126. # ARRAY
  127. $rows = Array();
  128. # LOOP: Get the tables
  129. foreach ($this->db->query("DESCRIBE " . $table[0]) AS $row) {
  130. $rows[] = "`" . $row[0] . "`";
  131. }
  132. $sqldump .= implode(', ', $rows);
  133. $sqldump .= ") VALUES\n";
  134. # COUNT
  135. $c = 0;
  136. # LOOP: Get the tables
  137. foreach ($this->db->query("SELECT * FROM " . $table[0]) AS $data) {
  138. # COUNT
  139. $c++;
  140. /** ** ** ** ** **/
  141. $sqldump .= "(";
  142. # ARRAY
  143. $cdata = Array();
  144. # LOOP
  145. for ($i = 0; $i < $c_rows; $i++) {
  146. if (is_null($data[$i])) {
  147. $cdata[] = "null";
  148. } else {
  149. $new_lines = preg_replace('/\s\s+/', '\r\n\r\n', addslashes($data[$i]));
  150. $cdata[] = "'" . $new_lines . "'";
  151. }
  152. }
  153. $sqldump .= implode(', ', $cdata);
  154. $sqldump .= ")";
  155. $sqldump .= ($c % 600 != 0 ? ($c_columns != $c ? ',' : ';') : '');
  156. # CHECK
  157. if ($c % 600 == 0) {
  158. $sqldump .= ";\n\n";
  159. } else {
  160. $sqldump .= "\n";
  161. }
  162. # CHECK
  163. if ($c % 600 == 0) {
  164. $sqldump .= "INSERT INTO " . $table[0] . "(";
  165. # ARRAY
  166. $rows = Array();
  167. # LOOP: Get the tables
  168. foreach ($this->db->query("DESCRIBE " . $table[0]) AS $row) {
  169. $rows[] = "`" . $row[0] . "`";
  170. }
  171. $sqldump .= implode(', ', $rows);
  172. $sqldump .= ") VALUES\n";
  173. }
  174. }
  175. }
  176. }
  177. $sqldump .= "\n\n\n";
  178. // Backup views
  179. $tables = $this->db->query("SHOW FULL TABLES WHERE Table_Type = 'VIEW'");
  180. # LOOP: Get the tables
  181. foreach ($tables AS $table) {
  182. // 忽略表
  183. if (in_array($table[0], $this->ignoreTables)) {
  184. continue;
  185. }
  186. foreach ($this->db->query("SHOW CREATE VIEW " . $table[0]) AS $field) {
  187. $sqldump .= "--\n";
  188. $sqldump .= "-- Remove the view if it exists\n";
  189. $sqldump .= "--\n\n";
  190. $sqldump .= "DROP VIEW IF EXISTS `{$field[0]}`;\n\n";
  191. $sqldump .= "--\n";
  192. $sqldump .= "-- Create the view if it not exists\n";
  193. $sqldump .= "--\n\n";
  194. $sqldump .= "{$field[1]};\n\n";
  195. }
  196. }
  197. return $sqldump;
  198. }
  199. }