首页> 实战笔录 >PHP开发笔记 >ThinkPHP ThinkPHP
TP5 databackup拓展插件,实现数据库备份下载还原代码分享
作者:小萝卜 2022-10-25 【 PHP TP5 】 浏览 768
简介TP5 databackup拓展插件,实现数据库备份下载还原代码分享
安装拓展:
控制器代码:
composer require tp5er/tp5-databackup dev-master
控制器代码:
<?php
namespace Admin\admin\controller;
use think\Controller;
use think\Db;
use think\Request;
use think\Session;
use \tp5er\Backup;
use Admin\admin\controller\IsLogins;
/**
* 数据库备份还原控制器
*/
class Databak extends Islogins{
public function index()
{
$db= new Backup();
return $this->fetch('index',['list'=>$db->dataList()]);
}
//备份文件列表
public function importlist()
{
$db= new Backup();
return $this->fetch('importlist',['list'=>$db->fileList()]);
}
public function import($time = 0, $part = null, $start = null)
{
$db= new Backup();
if(is_numeric($time) && is_null($part) && is_null($start)){
$list = $db->getFile('timeverif',$time);
if(is_array($list)){
session::set('backup_list', $list);
$this->success('初始化完成!', '', array('part' => 1, 'start' => 0));
}else{
$this->error('备份文件可能已经损坏,请检查!');
}
}else if(is_numeric($part) && is_numeric($start)){
$list=session::get('backup_list');
$start= $db->setFile($list)->import($start);
if( false===$start){
$this->error('还原数据出错!');
}elseif(0 === $start){
if(isset($list[++$part])){
$data = array('part' => $part, 'start' => 0);
$this->success("正在还原...#{$part}", '', $data);
} else {
session::delete('backup_list');
$this->success('还原完成!');
}
}else{
$data = array('part' => $part, 'start' => $start[0]);
if($start[1]){
$rate = floor(100 * ($start[0] / $start[1]));
$this->success("正在还原...#{$part} ({$rate}%)", '', $data);
} else {
$data['gz'] = 1;
$this->success("正在还原...#{$part}", '', $data);
}
$this->success("正在还原...#{$part}", '');
}
}else{
$this->error('参数错误!');
}
}
/**
* 删除备份文件
*/
public function del($time = 0){
$db= new Backup();
if($db->delFile($time)){
$this->success("备份文件删除成功!");
}else{
$this->error("备份文件删除失败,请检查权限!");
}
}
/**
* 下载备份文件
*/
public function down($time = 0){
$db= new Backup();
$db->downloadFile($time);
}
//备份表
public function export()
{
$db= new Backup();
if(Request::instance()->isPost()){
$input=input('post.');
$fileinfo =$db->getFile();
//检查是否有正在执行的任务
$lock = "{$fileinfo['filepath']}backup.lock";
if(is_file($lock)){
$this->error('检测到有一个备份任务正在执行,请稍后再试!');
} else {
//创建锁文件
file_put_contents($lock,time());
}
// 检查备份目录是否可写
is_writeable($fileinfo['filepath']) || $this->error('备份目录不存在或不可写,请检查后重试!');
//缓存锁文件
session::set('lock', $lock);
//缓存备份文件信息
session::set('backup_file', $fileinfo['file']);
//缓存要备份的表
session::set('backup_tables', $input['tables']);
//创建备份文件
if(false !== $db->Backup_Init()){
$this->success('初始化成功!','',['tab'=>['id' => 0, 'start' => 0]]);
}else{
$this->error('初始化失败,备份文件创建失败!');
}
}else if(Request::instance()->isGet()){
$tables = session::get('backup_tables');
$file=session::get('backup_file');
$id=input('id');
$start=input('start');
$start= $db->setFile($file)->backup($tables[$id], $start);
if(false === $start){
$this->error('备份出错!');
}else if(0 === $start){
if(isset($tables[++$id])){
$tab = array('id' => $id, 'start' => 0);
$this->success('备份完成!', '', array('tab' => $tab));
//$this->success("正在备份...#{$id}",array('tab' => $tab));
} else { //备份完成,清空缓存
unlink(session::get('lock'));
Session::delete('backup_tables');
Session::delete('backup_file');
$this->success('备份完成1!');
}
}else {
$tab = array('id' => $id, 'start' => $start[0]);
$rate = floor(100 * ($start[0] / $start[1]));
$this->success("正在备份...({$rate}%)", '', array('tab' => $tab));
}
}else{
$this->error('参数错误!');
}
}
//修复表
public function repair($tables= null)
{
$db= new Backup();
if($db->repair($tables)){
$this->success("数据表修复完成!");
}else{
$this->error("数据表修复出错请重试");
}
}
//优化表
public function optimize($tables= null)
{
$db= new Backup();
if($db->optimize($tables)){
$this->success("数据表优化完成!");
}else{
$this->error("数据表优化出错请重试!");
}
}
}
备份HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link rel="stylesheet" type="text/css" href="__PUBLIC__/admin/layui/css/layui.css" media="all">
<script type="text/javascript" src="__PUBLIC__/admin/layui/layui.js"></script>
</head>
<body>
<br>
<script>
layui.use(['jquery','layer'],function(){
window.$ = layui.$;
var layer = layui.layer;
//备份表方法
$("#export").click(function(){
$(this).html("正在发送备份请求...");
$.post(
$("#export-form").attr("action"),
$("#export-form").serialize(),
function(data){
if(data.code==1){
$("#export").html( "开始备份,请不要关闭本页面!");
backup(data.data.tab);
window.onbeforeunload = function(){ return "正在备份数据库,请不要关闭!" }
}else{
layer.tips(data.msg, "#export", {
tips: [1, '#3595CC'],
time: 4000
});
$("#export").html("立即备份");
}
}, "json");
return false;
});
//递归备份表
function backup(tab,status){
status && showmsg(tab.id, "开始备份...(0%)");
$.get( $("#export-form").attr("action"), tab, function(data){
console.log(data)
if(data.code==1){
showmsg(tab, data.msg);
if(!$.isPlainObject(data.data.tab)){
$("#export").html("备份完成");
window.onbeforeunload = function(){ return null }
return;
}
backup(data.data.tab, tab.id != data.data.tab.id);
} else {
$("#export").html("立即备份");
}
}, "json");
}
//修改备份状态
function showmsg(tab, msg){
$("table tbody tr").eq(tab.id).find(".info").html(msg);
console.log(msg);
}
//优化表
$("#optimize").click(function(){
$('#optimize').html('正在优化...');
$.post(this.href, $("#export-form").serialize(), function(data){
layer.tips(data.msg, "#optimize", {
tips: [1, '#3595CC'],
time: 4000
});
$('#optimize').html('优化表');
}, "json");
return false;
});
//修复表
$("#repair").on("click",function(e){
$('#repair').html('正在修复...');
$.post(this.href, $("#export-form").serialize(), function(data){
layer.tips(data.msg, "#repair", {
tips: [1, '#3595CC'],
time: 4000
});
$('#repair').html('修复表');
}, "json");
return false;
});
//优化表—-单
$(".optimize").click(function(){
var _this=$(this);
_this.html('正在优化...');
$.post(this.href, {}, function(data){
layer.alert(data.msg);
_this.html('优化表');
}, "json");
return false;
});
//修复表-单
$(".repair").on("click",function(e){
var _this=$(this);
_this.html('正在修复...');
$.post(this.href, {}, function(data){
layer.alert(data.msg);
_this.html('修复表');
}, "json");
return false;
});
});
</script>
<div class="layui-form">
<a id="export" class="layui-btn" href="javascript:;" autocomplete="off">立即备份</a>
<a id="optimize" href="{?:url('optimize')?}" class="layui-btn ">优化表</a>
<a id="repair" href="{?:url('repair')?}" class="layui-btn">修复表</a>
<a href="{?:url('importlist')?}" class="layui-btn">还原数据库</a>
<form id="export-form" method="post" action="{?:url('export')?}">
<table class="layui-table">
<thead>
<tr>
<th width="48"><input class="check-all" checked="chedked" type="checkbox" value=""></th>
<th>表名</th>
<th>数据量</th>
<th>数据大小</th>
<th>创建时间</th>
<th>备份状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{?foreach name='list' item='table'?}
<tr>
<td>
<input class="ids" checked="chedked" type="checkbox" name="tables[]" value="{?$table.name?}" style="display:inline;">
</td>
<td>{?$table.name?}</td>
<td>{?$table.rows?}</td>
<td>{?$table.data_length|format_bytes?}</td>
<td>{?$table.create_time?}</td>
<td class="info">未备份</td>
<td>
<a href="{?:url('optimize',['tables'=>$table['name']])?}" class="optimize">优化表</a>
<a href="{?:url('repair',['tables'=>$table['name']])?}" class="repair">修复表</a>
<!-- <a href="{?:url('optimize',['tables'=>$table['name']])?}" class="optimize">优化表</a>
<a href="{?:url('repair',['tables'=>$table['name']])?}" class="repair">修复表</a> -->
</td>
</tr>
{?/foreach?}
</tbody>
</table>
</form>
</div>
</body>
</html>
还原列表html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link rel="stylesheet" type="text/css" href="__PUBLIC__/admin/layui/css/layui.css" media="all">
<script type="text/javascript" src="__PUBLIC__/admin/layui/layui.js"></script>
</head>
<body>
<br>
<div class="layui-form">
<a class="layui-btn" href="javascript:;" autocomplete="off"> 数据库还原 </a>
<table class="layui-table">
<thead>
<tr>
<th>数据库名称</th>
<th>卷数</th>
<th>压缩</th>
<th>数据大小</th>
<th>备份时间</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{?foreach name='list' item='data'?}
<tr>
<td>{?$data.time|date='Ymd-His',###?}</td>
<td>{?$data.part?}</td>
<td>{?$data.compress?}</td>
<td>{?$data.size|format_bytes?}</td>
<td>{?$key?}</td>
<td class="status">-</td>
<td class="action">
<a class="db-down" href="{?:url('down',['time'=>$data['time']])?}">下载</a>
<a class="db-import" href="{?:url('import',['time'=>$data['time']])?}">还原</a>
<a class="ajax-get confirm" href="{?:url('del',['time'=>$data['time']])?}">删除</a>
</td>
</tr>
{?/foreach?}
</tbody>
<script>
layui.use(['jquery','layer'],function(){
window.$ = layui.$;
var layer = layui.layer;
$(".db-import").click(function(){
var self = this, status = ".";
$(this).parent().prevAll('.status').html("").html('等待还原');
$.get(self.href, success, "json");
window.onbeforeunload = function(){ return "正在还原数据库,请不要关闭!" }
return false;
function success(data){
if(data.code==1){
$(self).parent().prev().text(data.msg);
if(data.data.part){
$.get(self.href,
{"part" : data.data.part, "start" : data.data.start},
success,
"json"
);
} else {
layer.alert(data.msg);
//window.onbeforeunload = function(){ return null; }
}
} else {
layer.alert(data.msg);
}
}
});
$('.ajax-get').click(function(){
var self=$(this);
$.post(this.href,{},function(data){
layer.alert(data.msg);
self.parent().parent().remove();
});
return false;
});
});
</script>
</table>
</div>
</body>
</html>
很赞哦! (0)