準(zhǔn)備
開(kāi)發(fā)環(huán)境:windows10 + phpstorm + xampp ?
使用的相關(guān)組件 前端:AceAdmin后臺(tái)管理模版 + Jquery UI ?后端:thinkphp3.2.2版本
前言:小弟初來(lái)乍道怔檩,望有問(wèn)題可以互相交流掸犬,互相進(jìn)步肮塞,有更好的方法可以互相交流哈捎稚。今天在網(wǎng)上查找有關(guān)于 網(wǎng)頁(yè)版的mysql備份和還原的相關(guān)資料妒穴,學(xué)習(xí)一下,但是百度了不少漾脂,反反復(fù)復(fù)都是復(fù)制來(lái)復(fù)制去的棵磷,代碼相比較混亂,讓我看的很費(fèi)解玄渗,所以我打算自己來(lái)寫(xiě)個(gè)座菠。還有就是閱讀本文章需要有PHP的底子和對(duì)thinkphp框架比較了解,同時(shí)需要在mysql上面也需要一些了解藤树,特別是sql語(yǔ)句浴滴。
————————————我是可愛(ài)的分割線————————————
開(kāi)始
先來(lái)波效果圖感受下,這次先寫(xiě)備份岁钓,下次有時(shí)間再更新
步驟一:得到你需要操作的本地?cái)?shù)據(jù)庫(kù)中的表的列表巡莹,下面貼上代碼更直觀 ,有些注釋大神直接忽略甜紫,給有需要的人易于理解。
public ? function ?backupAndExport()?
{
$dataName= C("DB_NAME"); ?//獲取配置文件中配置的數(shù)據(jù)庫(kù)名稱
$this->assign("backupModuleCurrent","open active");//Ace框架顯示效果骂远,可忽略代碼
$sql="SHOW TABLE STATUS FROM ".$dataName;//列出數(shù)據(jù)庫(kù)所有的表
$tableList= M()->query($sql);
$databaseCount='';//統(tǒng)計(jì)數(shù)據(jù)庫(kù)大小初始化變量
//組裝變量 將表大小data_length 和 碎片data_free轉(zhuǎn)化為kb大小
foreach($tableList ?as ?&$tv)
{
$tv['table_size'] = intval($tv['data_length']/1024*100)/100;
$tv['table_free'] = intval($tv['data_free']/1024*100)/100;
$databaseCount+=$tv['table_size'];
}
//單位換算
if(intval($databaseCount) >1024)
{
$databaseCount= intval($databaseCount/1024*100)/100;
$databaseCount=$databaseCount.'MB';
}
else
{
$databaseCount=$databaseCount.'KB';
}
$this->assign("databaseCount",$databaseCount);
$this->assign("tableList",$tableList);
$this->display();
}
步驟一列表頁(yè)面完畢
————————————我是可愛(ài)的分割線———————————
步驟二:編寫(xiě)優(yōu)化按鈕和備份按鈕的事件囚霸,由于我的事件操作都是ajax完成的。所以需要在前端方面需要一定的了解激才。
//優(yōu)化表事件請(qǐng)求方法 這個(gè)還是比較簡(jiǎn)單的?
public function ?optimizeTable()
{
$return=array('code'=>0,'msg'=>'操作失斖匦汀!','data'=>'');//ajax請(qǐng)求返回參數(shù)
$success=array('code'=>200,'msg'=>'操作成功瘸恼!','data'=>'');
$table= text($_POST['table']);//接收POST過(guò)來(lái)的表名稱
$sql="OPTIMIZE TABLE ".$table;
$result= M()->query($sql);
if($result)
{
exit(json_encode($success));
}
else
{
exit(json_encode($return));
}
}
OPTIMIZE TABLE $table_name 這條sql語(yǔ)句想要深入了解的就需要自行百度下啦劣挫,這里就不敘述,以免篇幅過(guò)長(zhǎng)东帅。
————————————我是可愛(ài)的分割線———————————
步驟三:接下來(lái)是本文的重點(diǎn)压固。我的思路是先把單表的備份寫(xiě)好了,我想全部備份應(yīng)該也沒(méi)啥問(wèn)題靠闭,所以結(jié)果當(dāng)然也是我想的那樣帐我,相當(dāng)順利。
//單表備份
public function ?backupTable()
{
$backup_url='./data/database/';//先定義好數(shù)據(jù)庫(kù)文件備份位置
$return=array('code'=>0,'msg'=>'操作失斃颉拦键!','data'=>'');
$success=array('code'=>200,'msg'=>'操作成功!','data'=>'');
$table= text($_POST['table']);
$sql='show create table '.$table;//獲取表結(jié)構(gòu)
$tableDesc= M()->query($sql);
//備份表結(jié)構(gòu) 和 表數(shù)據(jù)
if(!empty($tableDesc[0]['create table']))//判斷是否存在表數(shù)據(jù)結(jié)構(gòu)
{
$backupStr='#ForAcerCms Backup File'."\n\n";//拼接自定義注釋語(yǔ)句 \n是寫(xiě)入文件的linux換行符 \r\n 是windows里面的而且換行符一定要放在 "\n"雙引號(hào)內(nèi)檩淋,單引號(hào)是沒(méi)用的芬为。
$backupStr.='#table : '.$table.' , backup time '.date('Y-m-d H:i:s', time())."\n\n";//拼接自定義注釋語(yǔ)句
$backupStr.='DROP TABLE IF EXISTS '.$table.';'."\n";//拼接自定義注釋語(yǔ)句
$backupStr.=$tableDesc[0]['create table'].';'."\n\n";//將表結(jié)構(gòu)放入到自定義字符串中
//取表字段 這個(gè)很重要
$getTableField='show columns from '.$table;
$tableFieldList= M()->query($getTableField);
$fieldListData= getSubByKey($tableFieldList,'field'); //這個(gè)方法是 從一個(gè)二維數(shù)組中 抽取某一個(gè)字段數(shù)據(jù)成一維數(shù)組
$fieldList= implode(',',$fieldListData);//將一維數(shù)組使用 , 分隔開(kāi)其實(shí)這步可以不用可以省略
//讀取表數(shù)據(jù)
$getSql="select * from ".$table;
$tableDataList= M()->query($getSql);
//組裝數(shù)據(jù)將 獲得的數(shù)據(jù) 拼裝成 insert into $table_name value();的字符串
foreach($tableDataListas$v)
{
$valueStr='';
for($i=0;$i
{
if($i== count($v)-1)
{
$valueStr.="'".$v[$fieldListData[$i]]."'";
}
else
{
$valueStr.="'".$v[$fieldListData[$i]]."'".',';
}
}
$backupStr.='insert into '.$table.' values ('.$valueStr.');'."\n";
}
//寫(xiě)入文件 之后把封裝好的 $backupStr 寫(xiě)入到自定義文件中sql中,也可以用作sql導(dǎo)入文件媚朦,親測(cè)有效氧敢。
$file_name=$table.'_'.date('YmdHis', time()).'.sql';
$file_url=$backup_url.$file_name;
$file= fopen($file_url,"w+");
$result= fwrite($file,$backupStr);
fclose($file);
}
else
{
exit(json_encode($return));
}
if($result)
{
exit(json_encode($success));
}
else
{
exit(json_encode($return));
}
}
單表的完成之后,多表的就簡(jiǎn)單啦莲镣,就是在獲取table那個(gè)位置增加一層對(duì)table的循環(huán)福稳。這樣就比較費(fèi)時(shí)了,所以在用戶操作的時(shí)候一定要提示用戶在備份中或者禁止用戶操作刷新頁(yè)面瑞侮,不然備份會(huì)被中斷而失敗的圆。之后這里貼上多表備份的代碼,稍稍的有一些不同半火,代碼都是大同小異的越妈。各位看官請(qǐng)看:
//多表備份
public function backupAllTable()
{
$backup_url='./data/database/';
$return=array('code'=>0,'msg'=>'操作失敗钮糖!','data'=>'');
$success=array('code'=>200,'msg'=>'操作成功梅掠!','data'=>'');
$dataName= C("DB_NAME");
$getTableListsql="SHOW TABLE STATUS FROM ".$dataName;//列出數(shù)據(jù)庫(kù)所有的表
$tableList= M()->query($getTableListsql);
$backupStr='#ForAcerCms Backup File'."\n\n";
foreach($tableListas$tv)
{
$table=$tv['name'];
$sql='show create table '.$table;
$tableDesc= M()->query($sql);
//備份表結(jié)構(gòu) 和 表數(shù)據(jù)
if(!empty($tableDesc[0]['create table']))
{
$backupStr.='#table : '.$table.' , backup time '.date('Y-m-d H:i:s', time())."\n\n";
$backupStr.='DROP TABLE IF EXISTS '.$table.';'."\n";
$backupStr.=$tableDesc[0]['create table'].';'."\n\n";
//取表字段
$getTableField='show columns from '.$table;
$tableFieldList= M()->query($getTableField);
$fieldListData= getSubByKey($tableFieldList,'field');
$fieldList= implode(',',$fieldListData);
//讀取表數(shù)據(jù)
$getSql="select * from ".$table;
$tableDataList= M()->query($getSql);
foreach($tableDataList as $key=>$v)
{
$valueStr='';
for($i=0;$i
{
if($i== count($v)-1)
{
$valueStr.="'".$v[$fieldListData[$i]]."'";
}
else
{
$valueStr.="'".$v[$fieldListData[$i]]."'".',';
}
}
if(count($tableDataList)-1==$key)
{
$backupStr.='insert into '.$table.' values ('.$valueStr.');'."\n\n\n";
}
else
{
$backupStr.='insert into '.$table.' values ('.$valueStr.');'."\n";
}
}
}
else
{
exit(json_encode($return));
}
}
//寫(xiě)入文件
$file_name='cms_system_'.date('YmdHis', time()).'.sql';
$file_url=$backup_url.$file_name;
$file= fopen($file_url,"w+");
$result= fwrite($file,$backupStr);
fclose($file);
if($result)
{
exit(json_encode($success));
}
else
{
exit(json_encode($return));
}
}
最后來(lái)一張效果圖:
————————————我是可愛(ài)的分割線———————————
步驟三結(jié)束啦,看到這里你看懂了嗎店归?沒(méi)看懂沒(méi)事阎抒,有疑問(wèn)可以提出來(lái),互相交流一下消痛,作為一個(gè)程序員且叁,討論問(wèn)題是最有趣的了,比如說(shuō):PHP是世界上最好的編程語(yǔ)言秩伞,沒(méi)有之一(手動(dòng)滑稽)逞带!
「everything has a price」