[英]creating a backup using php on localhost and server
我創建了自己的備份系統來備份數據庫和站點上可能更改的各種文件夾(為簡單起見,假設一個文件夾-> folder_to_backup
以及要保留的其中的文件和文件夾 )。 唯一的問題是,它在本地環境(本地主機)上不起作用,這是我要解決的問題。 這是進行實際壓縮的類(忘了我從哪里得到的):
function __construct($file, $folders = array(), $ignored = NULL)
{
$this->zip = new ZipArchive();
$this->ignored_names = is_array($ignored) ? $ignored : $ignored ? array(
$ignored
) : array();
if ($this->zip->open($file, ZIPARCHIVE::CREATE) !== TRUE) {
return FALSE;
}
$folder = substr($folder, -1) == '/' ? substr($folder, 0, strlen($folder) - 1) : $folder;
if (strstr($folder, '/')) {
$this->root = substr($folder, 0, strrpos($folder, '/') + 1);
$folder = substr($folder, strrpos($folder, '/') + 1);
}
foreach ($folders as $folder) {
$this->zip($folder);
}
$this->zip->close();
}
function zip($folder, $parent = NULL)
{
$full_path = $this->root . $parent . $folder;
$zip_path = $parent . $folder;
$this->zip->addEmptyDir($zip_path);
$dir = new DirectoryIterator($full_path);
foreach ($dir as $file) {
if (!$file->isDot()) {
$filename = $file->getFilename();
if (!in_array($filename, $this->ignored_names)) {
if ($file->isDir()) {
$this->zip($filename, $zip_path . '/');
} else {
$this->zip->addFile($full_path . '/' . $filename, $zip_path . '/' . $filename);
}
}
}
}
}
因此,使用上面的代碼創建了我的zip文件,但是我必須向$folder
發送帶有realpath()
的迭代器才能工作,因此在本地環境中,我會得到以下信息:
C:\\xampp\\htdocs\\sitename\\cms\\files\\folder_to_backup\\
並在http環境中:
/opt/www/prezent/sitename/HTML/cms/files/folder_to_backup/
所以說我想更新站點的本地主機副本,我下載了文件,由於明顯的原因,我無法解壓縮該文件,因為目錄結構不兼容,目錄分隔符也不兼容。
所以我想我可以將通用性隔離為'cms' . DIRECTORY_SEPARATOR . 'files' . DIRECTORY_SEPARATOR . 'folder_to_backup
'cms' . DIRECTORY_SEPARATOR . 'files' . DIRECTORY_SEPARATOR . 'folder_to_backup
'cms' . DIRECTORY_SEPARATOR . 'files' . DIRECTORY_SEPARATOR . 'folder_to_backup
。 因此,從本質上講,不是讓所有文件夾都指向文件夾cms,而是讓結構
DIR
files /
folder_to_backup /
some files and folders ... etc
然后還原,而不是通過realpath(DIRECTORY_SEPARATOR)
將其提取到/opt/
或C:\\
。 我會使用類似於realpath(dirname(__FILE__))
或您擁有的東西。
簡而言之,我的問題是我如何才能獲得上述文件結構(不包括/files/
的realpath,知道我必須向zip創建者提供一個realpath以便它可以找到文件?
使用此腳本:
1)如果您的站點很大並且將花費大量時間進行備份,則將執行時間設置為0,因為PHP的默認執行時間為30秒。
ini_set("max_execution_time", 0);
2)通過使用以下代碼,我們創建了一個目錄,您將在其中存儲zip。 在我的情況下,我的目錄名稱是“ site-backup-stark”。
$dir = "site-backup-stark";
if(!(file_exists($dir))) {
mkdir($dir, 0777);
}
3)設置您的站點憑據。
$host = "localhost"; //host name
$username = "root"; //username
$password = ""; // your password
$dbname = "wp_test"; // database name
4)我們將以zip格式保存備份,因此創建一個zip對象。
$zip = new ZipArchive();
5)調用函數backup_tables。
backup_tables($host, $username, $password, $dbname);
6)定義函數backup_tables,它將創建數據庫sql文件。
/* backup the db OR just a table */
function backup_tables($host,$user,$pass,$name,$tables = '*')
{
$con = mysql_connect($host,$user,$pass);
mysql_select_db($name,$con);
//get all of the tables
if($tables == '*')
{
$tables = array();
$result = mysql_query('SHOW TABLES');
while($row = mysql_fetch_row($result))
{
$tables[] = $row[0];
}
}
else
{
$tables = is_array($tables) ? $tables : explode(',',$tables);
}
$return = "";
//cycle through
foreach($tables as $table)
{
$result = mysql_query('SELECT * FROM '.$table);
$num_fields = mysql_num_fields($result);
$return.= 'DROP TABLE '.$table.';';
$row2 = mysql_fetch_row(mysql_query('SHOW CREATE TABLE '.$table));
$return.= "nn".$row2[1].";nn";
while($row = mysql_fetch_row($result))
{
$return.= 'INSERT INTO '.$table.' VALUES(';
for($j=0; $j<$num_fields; $j++)
{
$row[$j] = addslashes($row[$j]);
$row[$j] = preg_replace("#n#","n",$row[$j]);
if (isset($row[$j])) { $return.= '"'.$row[$j].'"' ; } else { $return.= '""'; }
if ($j<($num_fields-1)) { $return.= ','; }
}
$return.= ");n";
}
$return.="nnn";
}
//save file
$handle = fopen('db-backup-'.time().'-'.(md5(implode(',',$tables))).'.sql','w+');
fwrite($handle,$return);
fclose($handle);
}
7)將.sql文件轉換為.sql.zip文件,然后刪除.sql文件。
if (glob("*.sql") != false)
{
$filecount = count(glob("*.sql"));
$arr_file = glob("*.sql");
for($j=0;$j<$filecount;$j++)
{
$res = $zip->open($arr_file[$j].".zip", ZipArchive::CREATE);
if ($res === TRUE)
{
$zip->addFile($arr_file[$j]);
$zip->close();
unlink($arr_file[$j]);
}
}
}
8)現在,我們必須獲取其中存在我們的php文件的當前文件夾名稱。 這是因為當我們必須將所有文件夾和文件從根目錄移動到zip時。
//get the current folder name-start
$path = dirname($_SERVER['PHP_SELF']);
$position = strrpos($path,'/') + 1;
$folder_name = substr($path,$position);
//get the current folder name-end
9)為zip文件創建一個名稱。 我已經根據今天的日期創建了它,以便我們可以輕松找到上次備份的日期。 另外,我在后面的過程中使用的zip文件名稱后附加了“ stark-”。
$zipname = date('Y/m/d');
$str = "stark-".$zipname.".zip";
$str = str_replace("/", "-", $str);
10)將當前文件夾中的所有文件添加到新創建的zip文件中。
// open archive
if ($zip->open($str, ZIPARCHIVE::CREATE) !== TRUE) {
die ("Could not open archive");
}
// initialize an iterator
// pass it the directory to be processed
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator("../$folder_name /"));
// iterate over the directory
// add each file found to the archive
foreach ($iterator as $key=>$value) {
if( strstr(realpath($key), "stark") == FALSE) {
$zip->addFile(realpath($key), $key) or die ("ERROR: Could not add file: $key");
}
}
// close and save archive
$zip->close();
echo "Archive created successfully.";
11)當我們將它移到另一個文件夾中時,從根目錄中刪除所有.sql.zip文件。
if(glob("*.sql.zip") != false) {
$filecount = count(glob("*.sql.zip"));
$arr_file = glob("*.sql.zip");
for($j=0;$j<$filecount;$j++)
{
unlink($arr_file[$j]);
}
}
12)現在,將我們的zip文件的副本移至在步驟2中創建的目錄。
//get the array of zip files
if(glob("*.zip") != false) {
$arr_zip = glob("*.zip");
}
//copy the backup zip file to site-backup-stark folder
foreach ($arr_zip as $key => $value) {
if (strstr($value, "stark")) {
$delete_zip[] = $value;
copy("$value", "$dir/$value");
}
}
13)當我們將其移動到另一個目錄時,請從根目錄中刪除一個zip文件。
for ($i=0; $i < count($delete_zip); $i++) {
unlink($delete_zip[$i]);
}
因此,由於我找不到直接的答案,而且一無所獲,因此我在該站點上進行了很多研究,並通過查找其他備份方法進行了研究,因此我開始創建一個類,該類將與此有關的堆棧上的許多答案組合到了一起一堂課 我什至還添加了一種忽略文件和文件夾的方法,以及一種自動查找實際zip體系結構應從哪個目錄開始的自動化方法。我已經確認它可以在Windows(通過xampp)和我的站點服務器上運行。 希望這可以節省一些人的頭痛!
在課程結束時概述用法! 如果有人想重構它,請放心,但是要對其進行測試,然后更新我的答案!
<?php
class ZipFolder
{
/** NON CONFIGURABLE **/
protected $zip;
protected $SQLinit = false;
/** CONFIGURABLE **/
protected $overwrite = true; // overwrite file if exists (just incase unlink doesnt work)
protected $nback = 1; /* if you have a folder such as /HTML/ in your doc root and
your website index.html begings in the /HTML/ dir this
number should be one. add +1 for every directory until your
website frontend homepage */
protected $sqlDirInZip = 'sql'; // sql dir inside
protected $ignored_files = array('.DS_STORE'); // specific files to ignore (Note: also works with extensions)
protected $ignored_folders = array('_notes'); // folders to ignore
function __construct($destination, $sources = array(), $SQLfile = NULL)
{
if (!extension_loaded('zip')) {
return false;
}
$this->zip = new ZipArchive();
if (file_exists($destination)) {
@unlink($destination);
}
// ZIPARCHIVE::OVERWRITE ??
if ($this->zip->open($destination, $this->overwrite == true ? ZIPARCHIVE::OVERWRITE : ZIPARCHIVE::CREATE) !== TRUE) {
return false;
}
if (isset($SQLfile)) {
// zip sql file in sql directory
$this->SQLinit = true;
$SQLfile = str_replace('\\', DIRECTORY_SEPARATOR, realpath($SQLfile));
$this->zip->addEmptyDir($this->sqlDirInZip);
$this->zip->addFromString($this->sqlDirInZip . DIRECTORY_SEPARATOR . basename($SQLfile), file_get_contents($SQLfile));
}
foreach ($sources as $source) {
$this->zippy($source, true);
}
if ($this->SQLinit) {
if (!$this->verifySQL($destination)) {
// couldn't verify that sql made it we close dir and remove it, return a false
$this->zip->close();
unlink($destination);
return false;
}
}
$this->zip->close();
return true;
}
/**
*
* Count Slashes
*
* Given a $str will return the amount of slashes in the string
* We can use this to find the diff (new func needed) between
* /HTML/ and where we are now, and then send that number to minus
*
* string $str
* boolean $normalizeHttp will normalize to \ slash
*/
function count_slashes($str, $normalizeHttp = false)
{
$slash = $normalizeHttp ? '\\' : '/';
$n = 0;
for ($i = 0; $i < strlen($str); $i++)
{
if ($str[$i] == $slash)
$n++;
}
return $n;
}
/**
* Directory Difference
*
* Will find the diffrence between the document root, and the source
* with is the relative path to this class, and return a number based
* on the number of slashes in the string that makes up the diffrence
*
* string $source
* int $offset value of 1 offeset directory forward one directory
* from /HTML/foo/bar/ to /foo/bar/
*
*/
function dirDiff($source, $offset = 0) {
$docRoot = str_replace('/', '\\', $_SERVER['DOCUMENT_ROOT']); // normalize to http
$diff = str_replace($docRoot, '', $source);
return $this->count_slashes($diff, true) - $offset; // removed ltrim to trim beginning slash of diff
}
/**
*
* zippy
*
* Creates a zip file from a $source directory
* $include_dir = true means we get the parent directories up until the root directory
* otherwise, we just put in the $source dir and its children.
*
* string $source
* boolean $include_dir
*
*/
function zippy($source, $include_dir = false)
{
$source = str_replace('\\', DIRECTORY_SEPARATOR, realpath($source));
if (is_dir($source) === true) {
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source), RecursiveIteratorIterator::SELF_FIRST);
// this is where we figure out where to start and how to format the directories
if ($include_dir) {
$goForward = $this->dirDiff($source, $this->nback);
$arrDir = explode(DIRECTORY_SEPARATOR, $source);
$maindir = $arrDir[count($arrDir) - $goForward];
$this->zip->addEmptyDir($maindir);
$source = "";
for ($i = 0; $i < count($arrDir) - $goForward; $i++) {
$source .= DIRECTORY_SEPARATOR . $arrDir[$i];
}
$source = substr($source, 1);
}
foreach ($files as $file) {
$file = str_replace('\\', DIRECTORY_SEPARATOR, $file);
// ignore "." and ".." folders (Note: isDot() fails to work)
if (in_array(substr($file, strrpos($file, DIRECTORY_SEPARATOR) + 1), array('.', '..'))) {
continue; // exit out of loop
}
$file = realpath($file);
if (is_dir($file) === true) {
if (!in_array(basename($file), $this->ignored_folders)) {
$this->zip->addEmptyDir(str_replace($source . DIRECTORY_SEPARATOR, '', $file . DIRECTORY_SEPARATOR));
} else {
continue;
}
} elseif (is_file($file) === true) {
// for some reason addFromString iterates through dirs that are exlcuded folders
// so we remove ignored folders here to via a strpos hack
if (!in_array(basename($file), $this->ignored_files) && $this->strposArray($file, $this->ignored_folders, 1) == false) {
$this->zip->addFromString(str_replace($source . DIRECTORY_SEPARATOR, '', $file), file_get_contents($file));
} else {
continue;
}
}
}
} else if (is_file($source) === true) {
$this->zip->addFromString(basename($source), file_get_contents($source));
}
}
/**
*
* strposArray
*
* Array usage of strpos
* Returns false on first true matching result from the given array
*
* string $haystack
* string || array $needle
* int $offset
*
*/
function strposArray($haystack, $needle, $offset= 0 ) {
if(!is_array($needle)) {
$needle = array($needle);
}
foreach($needle as $query) {
if(strpos($haystack, $query, $offset) !== false) return true; // stop on first true result
}
return false;
}
/**
* verifySQL
*
* Called to check that the $sqlDirInZip exists
* Returns false on failure to affirm the above
*
*/
function verifySQL()
{
// the '/sql' dir exists
// we want to use '/' instead of directory sep bc windows looks up in zips / instead of \
if ($this->zip->statName($this->sqlDirInZip . '/') !== false) {
return true;
} else {
// no sql file
return false;
}
}
}
// all of the following paths in either as a destination or source can be real or absolute
$destination = 'newzippyzip.zip';
$sql = '../backup/test.sql';
if (new ZipFolder($destination, array('../images/', '../../images/uploads/'), $sql)) {
echo 'Done!';
}
?>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.