一下代码有些需要改动,有些为自己封装的函数,懒了直接上菜吧。慢慢改,不懂的咨询,看到会回复
分了两个文件 都是在模型控制器中
备份类
1 <?php 2 namespace app\admin\controller; 3 use think\Controller; 4 use think\Db; 5 6 //接口类 7 class Databackup extends Controller 8 { 9 10 // 任务--数据备份 11 public function do_tasks() 12 { 13 $this->backup(); 14 action('common/lib/adminLog',['数据备份--成功']); 15 } 16 17 18 // 数据备份 19 public function backup($sqlfilename='') 20 { 21 // 判断文件数量 22 $L=glob(ROOT_PATH.'data/sqldata/*.sql'); 23 $n=count($L); 24 if($n>10 && $L) 25 { 26 $L=array_reverse($L); 27 foreach ($L as $k => $v) { 28 if($k > 3) 29 { 30 if(is_file($v)) 31 { 32 unlink($v); 33 } 34 } 35 } 36 } 37 38 // 录入数据表缓存 39 $run_log = ROOT_PATH . 'data/sqldata/run.log'; 40 $sqlname=$sqlfilename==''?get_random_name():$sqlfilename;//备份文件名 41 // 文件地址 42 $path=ROOT_PATH . 'data/sqldata/' . $sqlname . '.sql'; 43 $max_size=512000;//分卷备份 - 文件长度限制(kb) 44 // 全部备份 45 $prefix=config('database.prefix'); 46 $sql="SHOW TABLE STATUS LIKE '" . $prefix . "%'"; 47 $ret = Db::query($sql); 48 $tables=[]; 49 if($ret) 50 { 51 foreach ($ret AS $table) 52 { 53 $tableName=$table['Name']; 54 $tables[$tableName]=-1; 55 } 56 } 57 58 $res=put_tables_list($run_log,$tables); 59 if($res['code']==0) 60 { 61 action('common/lib/adminLog',['数据备份----'.$res['msg']]); 62 return $this->error($res['msg']); 63 } 64 65 66 67 // 备份数据 68 $res=dump_table($run_log, $path,$max_size); 69 if(IS_CLI==false && $sqlfilename=='') 70 { 71 if($res['code']==0) 72 { 73 action('common/lib/adminLog',['数据备份----'.$res['msg']]); 74 return $this->error($res['msg']); 75 }else{ 76 action('common/lib/adminLog',['数据备份--成功']); 77 return $this->success('备份成功'); 78 } 79 }else{ 80 return $res; 81 } 82 83 } 84 85 86 } 87 88 89 90 91 // 创建备份文件名 92 function get_random_name() 93 { 94 $str = date('YmdHis').'_'; 95 96 for ($i = 0; $i < 6; $i++) 97 { 98 $str .= chr(mt_rand(97, 122)); 99 } 100 101 return $str; 102 } 103 104 105 106 107 /** 108 * 生成备份文件头部 109 * 110 * @access public 111 * @param int 文件卷数 112 * 113 * @return string $str 备份文件头部 114 */ 115 function make_head() 116 { 117 $version = Db::query('SELECT VERSION() AS ver'); 118 FLog($_SERVER); 119 /* 系统信息 */ 120 $sys_info['os'] = PHP_OS; 121 $sys_info['web_server'] = isset($_SERVER['HTTP_ORIGIN'])?$_SERVER['HTTP_ORIGIN']:'http://basesc.net'; 122 // $sys_info['server_ip'] = $_SERVER['SERVER_ADDR']; 123 $sys_info['php_ver'] = PHP_VERSION; 124 $sys_info['mysql_ver'] = $version[0]['ver']; 125 126 $sys_info['date'] = date('Y-m-d H:i:s'); 127 128 $head = "-- sjx v1.x SQL Dump Program\r\n". 129 "-- " . $sys_info['web_server'] . "\r\n". 130 "-- \r\n". 131 "-- DATE : ".$sys_info["date"]."\r\n". 132 "-- MYSQL SERVER VERSION : ".$sys_info['mysql_ver']."\r\n". 133 "-- PHP VERSION : ".$sys_info['php_ver']."\r\n"; 134 135 return $head; 136 } 137 138 /** 139 * 备份一个数据表 140 * 141 * @access public 142 * @param string $path 保存路径表名的文件 143 * @param int $vol 卷标 144 * 145 * @return array $tables 未备份完的表列表 146 */ 147 function dump_table($path, $sqlpath,$max_size) 148 { 149 $sql_num=0; 150 151 $tables = get_tables_list($path); 152 153 if ($tables === false) 154 { 155 return false; 156 } 157 158 if (empty($tables)) 159 { 160 return $tables; 161 } 162 163 $sql_head = make_head(); 164 165 166 foreach($tables as $table => $pos) 167 { 168 169 if ($pos == -1) 170 { 171 /* 获取表定义,如果没有超过限制则保存 */ 172 $table_df = get_table_df($table, true); 173 174 if ($sql_num == 0) 175 { 176 /* 第一条记录,强制写入 */ 177 $sql_head .= $table_df; 178 $sql_num +=2; 179 $tables[$table] = 0; 180 }else 181 { 182 $sql_head .= $table_df; 183 $sql_num +=2; 184 $pos = 0; 185 } 186 } 187 188 /* 尽可能多获取数据表数据 */ 189 $post_pos = get_table_data($table); 190 191 if ($post_pos['code'] == -1) 192 { 193 /* 该表已经完成,清除该表 */ 194 unset($tables[$table]); 195 }else if($post_pos['code']==0) 196 { 197 unset($tables[$table]); 198 $sql_head.=$post_pos['html']; 199 } 200 else 201 { 202 /* 该表未完成。说明将要到达上限,记录备份数据位置 */ 203 $tables[$table] = $post_pos; 204 $sql_head.=$post_pos['html']; 205 break; 206 } 207 208 } 209 210 $sql_head .= '-- END sjx v1.x SQL Dump Program '; 211 212 @file_put_contents($sqlpath, $sql_head); 213 214 $res=put_tables_list($path, $tables); 215 if($res['code']==0) 216 { 217 return ['code'=>0,'msg'=>$res['msg']]; 218 }else{ 219 return ['code'=>1,'msg'=>'','data'=>$tables]; 220 } 221 } 222 223 /** 224 * 将数据表数组写入指定文件 225 * 226 * @access public 227 * @param string $path 文件路径 228 * @param array $arr 要写入的数据 229 * 230 * @return boolen 231 */ 232 function put_tables_list($path, $arr,$data=[]) 233 { 234 if (is_array($arr)) 235 { 236 237 if($data) 238 { 239 $msg="/* \r\n"; 240 foreach ($data as $k1 => $v1) { 241 $msg .= $k1 . ': ' . $v1 . ";\r\n"; 242 } 243 $msg.="*/ \r\n"; 244 $str = $msg; 245 }else{ 246 $str = ''; 247 } 248 249 250 foreach($arr as $key => $val) 251 { 252 $str .= $key . ': ' . $val . ";\r\n"; 253 254 } 255 256 @file_put_contents($path, $str); 257 return ['code'=>1]; 258 } 259 else 260 { 261 return ['code'=>0,'msg'=>'It need a array']; 262 } 263 } 264 265 /** 266 * 将文件中数据表列表取出 267 * 268 * @access public 269 * @param string $path 文件路径 270 * 271 * @return array $arr 数据表列表 272 */ 273 function get_tables_list($path) 274 { 275 if (!file_exists($path)) 276 { 277 echo $path . ' is not exists'; 278 return false; 279 } 280 281 $arr = array(); 282 $str = @file_get_contents($path); 283 284 if (!empty($str)) 285 { 286 $tmp_arr = explode("\n", $str); 287 foreach ($tmp_arr as $val) 288 { 289 $val = trim ($val, "\r;"); 290 if (!empty($val)) 291 { 292 list($table, $count) = explode(':',$val); 293 $arr[$table] = $count; 294 } 295 } 296 } 297 298 return $arr; 299 } 300 301 302 /** 303 * 获取指定表的定义 304 * 305 * @access public 306 * @param string $table 数据表名 307 * @param boolen $add_drop 是否加入drop table 308 * 309 * @return string $sql 310 */ 311 function get_table_df($table, $add_drop = false) 312 { 313 $charset=config('database.charset'); 314 315 if ($add_drop) 316 { 317 $table_df = "DROP TABLE IF EXISTS `$table`;\r\n"; 318 } 319 else 320 { 321 $table_df = ''; 322 } 323 324 $tmp_arr = Db::query("SHOW CREATE TABLE `$table`"); 325 $tmp_sql = $tmp_arr[0]['Create Table']; 326 // $tmp_sql = substr($tmp_sql, 0, strrpos($tmp_sql, ")") + 1); //去除行尾定义。 327 // $table_df .= $tmp_sql . " ENGINE=MyISAM DEFAULT CHARSET=" . str_replace('-', '', $charset) . ";\r\n"; 328 329 $table_df .= $tmp_sql.";\r\n"; 330 331 return $table_df; 332 } 333 334 /** 335 * 获取指定表的数据定义 336 * 337 * @access public 338 * @param string $table 表名 339 * @param int $pos 备份开始位置 340 * 341 * @return int $post_pos 记录位置 342 */ 343 function get_table_data($table) 344 { 345 $offset=300; 346 $post_pos=0; 347 348 /* 获取数据表记录总数 */ 349 $total = Db::query("SELECT COUNT(*) as count FROM $table"); 350 $total=$total[0]['count']; 351 352 if ($total == 0) 353 { 354 /* 无须处理 */ 355 return ['code'=>-1]; 356 } 357 358 /* 确定循环次数 */ 359 $cycle_time = ceil(($total) / $offset); //每次取offset条数。需要取的次数 360 361 $dump_sql=""; 362 363 /* 循环查数据表 */ 364 for($i = 0; $i<$cycle_time; $i++) 365 { 366 367 /* 获取数据库数据 */ 368 $data = Db::query("SELECT * FROM $table LIMIT " . ($offset * $i) . ', ' . $offset); 369 $data_count = count($data); 370 371 372 $fields = array_keys($data[0]); 373 $start_sql = "INSERT INTO `$table` ( `" . implode("`, `", $fields) . "` ) VALUES "; 374 375 $tmp_dump_sql=''; 376 /* 循环将数据写入 */ 377 for($j=0; $j< $data_count; $j++) 378 { 379 $record = $data[$j]; 380 381 $tmp_dump_sql .= $start_sql." ( '" . implode("', '" , $record) . "' );\r\n"; 382 $post_pos++; 383 } 384 if($tmp_dump_sql!='') 385 { 386 $dump_sql .= $tmp_dump_sql; 387 } 388 389 390 } 391 392 if($total==$post_pos) 393 { 394 /* 所有数据已经写完 */ 395 return ['code'=>0,'html'=>$dump_sql]; 396 } 397 }
调用展示数据表类
1 <?php 2 namespace app\admin\controller; 3 use think\Db; 4 5 6 // 数据表接口 7 class Intdata extends Base 8 { 9 public function __construct(){ 10 parent::__construct(); 11 } 12 13 14 // 数据表列表--数据优化 15 public function index() 16 { 17 // 将当前数据库的表信息全部展示出来 18 $prefix=config('database.prefix'); 19 $sql="SHOW TABLE STATUS LIKE '" . $prefix . "%'"; 20 $ret = Db::query($sql); 21 22 $list=[]; 23 $count=count($list); 24 $num=0; 25 if($ret) 26 { 27 foreach ($ret as $k => $v) { 28 $num += $v['Data_free']; 29 $type = $v['Engine']; 30 $charset = $v['Collation']; 31 $list[] = [ 32 'table' => $v['Name'], 33 'type' => $type, 34 'rec_num' => $v['Rows'], 35 'rec_size' => sprintf(" %.2f KB", $v['Data_length'] / 1024), 36 // 'rec_index' => $v['Index_length'], 37 'rec_chip' => $v['Data_free'], 38 'charset' => $charset 39 ]; 40 } 41 } 42 43 $this->assign('list',$list); 44 $this->assign('num',$num); 45 $this->assign('count',$count); 46 return view(); 47 } 48 49 50 // 数据优化 只针对 engine=MyISAM 51 public function youhua() 52 { 53 $tableName=input('other',''); 54 if($tableName!='') 55 { 56 $row = Db::query('OPTIMIZE TABLE ' . $tableName); 57 if($row[0]) 58 { 59 $row=$row[0]; 60 /* 优化出错,尝试修复 */ 61 if ($row['Msg_type'] =='error' && strpos($row['Msg_text'], 'repair') !== false) 62 { 63 Db::query('REPAIR TABLE ' . $tableName); 64 } 65 } 66 return $this->success('优化成功'); 67 } 68 $prefix=config('database.prefix'); 69 $sql="SHOW TABLE STATUS LIKE '" . $prefix . "%'"; 70 $tables = Db::query($sql); 71 if($tables) 72 { 73 foreach ($tables AS $table) 74 { 75 $tableName=$table['Name']; 76 $row = Db::query('OPTIMIZE TABLE ' . $tableName); 77 if($row[0]) 78 { 79 $row=$row[0]; 80 /* 优化出错,尝试修复 */ 81 if ($row['Msg_type'] =='error' && strpos($row['Msg_text'], 'repair') !== false) 82 { 83 Db::query('REPAIR TABLE ' . $tableName); 84 } 85 } 86 } 87 } 88 89 90 return $this->success('优化成功'); 91 } 92 93 // 备份 94 public function backup() 95 { 96 action('Databackup/backup'); 97 } 98 99 // 数据备份列表 100 public function backup_list() 101 { 102 // echo '<pre>'; 103 $L=glob(ROOT_PATH.'data/sqldata/*.sql'); 104 $list=[]; 105 if($L) 106 { 107 $L=array_reverse($L); 108 foreach ($L as $k => &$v) { 109 $info=pathinfo($v); 110 $time=filectime($v); 111 $list[]=[ 112 'file_name'=>$info['filename'], 113 'file_time'=>date('Y-m-d H:i',$time), 114 ]; 115 } 116 } 117 $this->assign('list',$list); 118 return view(); 119 } 120 121 // 文件下载 122 public function getfile_bytes() 123 { 124 $filename=input('filename',''); 125 126 $path=ROOT_PATH.'data/sqldata/'.$filename.'.sql'; 127 if(!is_file($path)) 128 { 129 return $this->error('指定文件不存在'); 130 } 131 $filename.='.sql'; 132 action('common/Interfun/download',[$path,$filename]); 133 } 134 135 // 还原备份数据 136 public function return_data() 137 { 138 $filename=input('other',''); 139 $path=ROOT_PATH.'data/sqldata/'.$filename.'.sql'; 140 141 // 还原之前备份 142 action('Databackup/backup',$filename.'_returnBefore'); 143 144 $this->_import($path); 145 action('common/lib/adminLog',['数据还原---文件:'.$filename.'.sql']); 146 return $this->success('还原备份成功','intdata/index'); 147 } 148 149 150 151 // 删除备份数据 152 public function del() 153 { 154 $filename=input('other',''); 155 156 $path=ROOT_PATH.'data/sqldata/'.$filename.'.sql'; 157 if(!is_file($path)) 158 { 159 return $this->error('指定文件不存在'); 160 }else{ 161 action('common/lib/adminLog',['备份数据删除']); 162 unlink($path); 163 return $this->success('删除成功'); 164 } 165 } 166 167 /** 168 * 将sql导入到数据库(普通导入) 169 * 170 * @param string $sqlfile 171 * @return boolean 172 */ 173 private function _import($sqlfile) { 174 // sql文件包含的sql语句数组 175 $sqls = array (); 176 $f = fopen ( $sqlfile, "rb" ); 177 // 创建表缓冲变量 178 $create = ''; 179 while ( ! feof ( $f ) ) { 180 // 读取每一行sql 181 $line = fgets ( $f ); 182 // 如果包含'-- '等注释,或为空白行,则跳过 183 if (trim ( $line ) == '' || preg_match ( '/--*?/', $line, $match )) { 184 continue; 185 } 186 187 // 如果结尾包含';'(即为一个完整的sql语句,这里是插入语句),并且不包含'ENGINE='(即创建表的最后一句), 188 if (! preg_match ( '/;/', $line, $match ) || preg_match ( '/ENGINE=/', $line, $match )) { 189 // 将本次sql语句与创建表sql连接存起来 190 $create .= $line; 191 // 如果包含了创建表的最后一句 192 if (preg_match ( '/ENGINE=/', $create, $match )) { 193 // 则将其合并到sql数组 194 $sqls [] = $create; 195 // 清空当前,准备下一个表的创建 196 $create = ''; 197 } 198 // 跳过本次 199 continue; 200 } 201 $sqls [] = $line; 202 } 203 fclose ( $f ); 204 // 循环sql语句数组,分别执行 205 foreach ( $sqls as $sql ) { 206 $tables = Db::execute(trim ( $sql )); 207 } 208 return true; 209 } 210 211 212 213 214 215 216 217 218 219 220 221 // 批量修改数据表引擎 222 // public function alter_engine() 223 // { 224 // // 将数据表引擎转化 225 // $sql="SELECT TABLE_NAME FROM information_schema.TABLES where TABLE_SCHEMA='basesc2' and `ENGINE`='InnoDB' and TABLE_NAME LIKE 'sjx_%';"; 226 // $res = Db::query($sql); 227 // if($res) 228 // { 229 // foreach ($res as $k => $table) { 230 // $tableName=$table['TABLE_NAME']; 231 // $tables = Db::execute('alter table '.$tableName.' engine=MyISAM; '); 232 // } 233 // } 234 // } 235 236 237 238 239 240 }
在规矩中有自己的不规矩,走出不一样的路才是属于自己的路