[英]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.