Código PHP:
<?php
/* Copyright Edgar Alexander Franco 2012 */
class Backup extends ZipArchive
{
private $Id; // Identificador para el respaldo.
private $BackupDate; // Fecha del backup.
private $BackupTmpPath; // Ruta del archivo .zip temporal del backup.
private $Tables; // Tablas de la base de datos mysql.
private $iTables; // Índice de Tablas.
private $MysqlBackupContent; // Contenido del archivo .sql.
private $Error; // En caso de que no exista una Base de datos / Tabla / Directorio.
public $Statement; // Requerido. Un procedimiento de la clase mysqli.
public $MysqlDatabaseName; // Requerido. Nombre de la base de datos mysql.
public $Name; // Nombre para el backup (Por defecto es 'Backup').
public $Path; // Ruta dónde se gestionará el respaldo, si no se especifíca, se gestionará en la misma carpeta del script.
public $MysqlBackupName; // Nombre para el archivo .sql (Por defecto es 'MysqlBackup').
public function Backup()
{
$this->Id = time();
$this->BackupDate = date('d-m-Y H-i-s');
$this->Tables = array();
$this->iTables = 0;
$this->Name = 'Backup';
$this->Path = '';
$this->MysqlBackupName = "MysqlBackup";
$this->MysqlBackupContent = "";
$this->Error = "An error has ocurred, please remove the ". $this->BackupTmpPath. " file if exist and try again.";
}
public function Init()
{
// Crea un archivo .zip y establece su ruta.
$this->BackupTmpPath = $this->Path. $this->Name. '-'. $this->Id. '.zip';
$this->open($this->BackupTmpPath, ZIPARCHIVE::CREATE);
}
public function addTable($Table)
{
// Agrega una tabla mysql a respaldar.
$this->Tables[ $this->iTables ] = $Table;
$this->iTables++;
}
public function addFolder($FolderPath, $DestinationPath)
{
/*
* Agrega un directorio a respaldar (A excepción de subdirectorios).
* Primero validamos el directorio a respaldar.
*/
if(!is_dir($FolderPath))
{
die($this->Error);
}
// Abrimos el directorio a respaldar agregamos el directorio al archivo .zip.
$Dir = dir($FolderPath);
$this->addEmptyDir($DestinationPath);
while($File = $Dir->read())
{
$FilePath = $FolderPath. $File;
// Comprobamos que no sea otro directorio.
if($File != '.' && $File != '..' && !is_dir($FilePath))
{
// Agregamos el archivo al .zip.
$this->addFile($FilePath, $DestinationPath. '/'. $File);
}
}
}
public function generateMysqlBackup()
{
// Cabecera del archivo.
$this->MysqlBackupContent .= "-- Mysql Backup: ". $this->Id. " / ". $this->BackupDate. ".";
foreach($this->Tables as $Table)
{
/*
* Primero consultamos todos los datos de la tabla actual para
* verificar si hay registros.
*
* Si hay se crea un INSERT dentro del cuerpo del archivo,
* caso contrario se siguen evaluándo las otras tablas.
*/
$this->Statement->prepare('SELECT * FROM '. $Table) or die($this->Error);
$this->Statement->execute();
$ResultSet = $this->Statement->get_result();
$ValuesArray = $ResultSet->fetch_all(); // Obtenémos todos los registros de la tabla.
if($ResultSet->num_rows > 0)
{
// Si entrámos es porque existen registros, así que procedemos a crear el INSERT.
$Fields = ""; // Un string que concatena todos los campos de la tabla actual.
$Values = ""; // Un string que concatena todos los valores de la tabla actual.
// Cabecera para el INSERT de la tabla actual.
$this->MysqlBackupContent .= "\r\n\r\n-- Backup for the table '". $Table. "':";
// Consultamos los campos de la tabla INFORMATION_SCHEMA a través del nombre de la tabla actual y la base de datos especificada.
$this->Statement->prepare('SELECT column_name FROM INFORMATION_SCHEMA.columns WHERE table_name = ? AND table_schema = ?') or die($this->Error);
$this->Statement->bind_param('ss', $Table, $this->MysqlDatabaseName);
$this->Statement->execute();
$ResultSet = $this->Statement->get_result();
$FieldsArray = $ResultSet->fetch_all(); // Obtenémos todos los campos.
// Concatenámos los campos en un solo string.
foreach($FieldsArray as $Field)
{
$Fields .= $Field[0]. ", ";
}
// Concatenámos cada registro en un solo string.
foreach($ValuesArray as $Value)
{
$Values .= "(";
foreach($Value as $Val)
{
/*
* No se respétan los tipos de datos del todo,
* pero pienso que no hay ningún problema.
*/
$Val = mysql_real_escape_string($Val);
if($Val == '')
{
// Si está vacío es asignado a NULL.
$Values .= "NULL, ";
}
else
{
if($Val == '0' || $Val == '1')
{
/*
* Si es 0 o 1 lo asignamos como un tipo de dato numérico
* para evitar problemas con campos binarios (bit, tinyint).
*/
$Values .= $Val. ", ";
}
else
{
// Del resto es una cadena de caractéres.
$Values .= "'". $Val. "', ";
}
}
}
$Values = substr($Values, 0, -2);
$Values .= "), ";
}
$Fields = substr($Fields, 0, -2);
$Values = substr($Values, 0, -2);
// Terminámos el INSERT.
$this->MysqlBackupContent .= "\r\n\r\nINSERT INTO ". $Table. " (". $Fields. ") VALUES ". $Values. ";";
// Hacémos una pequeña pausa para optimizar el proceso.
time_nanosleep(0, 100000000); // Exáctamente 10 milisegundos
}
else
{
// Sino la tabla está vacía.
$this->MysqlBackupContent .= "\r\n\r\n-- Table '". $Table. "' is empty.";
}
}
// Agregámos el archivo .sql al archivo de respaldo .zip.
$this->addFromString($this->MysqlBackupName. '-'. $this->BackupDate. '.sql', $this->MysqlBackupContent);
}
public function SaveAndGet()
{
// Ya cerramos el archivo .zip.
$this->close();
// Obtenémos el contenido del archivo .zip.
$BackupName = $this->Name. '-'. $this->BackupDate. '.zip';
$BackupContent = file_get_contents($this->BackupTmpPath);
$BackupLength = strlen($BackupContent);
// Eliminamos el archivo .zip del servidor.
if(file_exists($this->BackupTmpPath))
{
unlink($this->BackupTmpPath);
}
// Se manda a descargar el respaldo.
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='. $BackupName);
header('Content-Length: '. $BackupLength);
echo $BackupContent;
}
}
?>
Luego para usarla aquí va un ejemplo:
Código PHP:
<?php
include('Backup.php');
// Crea tu objeto mysqli y seguido un procedimiento.
$Servidor = 'localhost';
$Usuario = 'Usuario';
$Contrasena = 'Contraseña';
$BaseDeDatos = 'TuBaseDeDatos';
$mysqli = new mysqli($Servidor, $Usuario, $Contrasena, $BaseDeDatos);
$stmt = $mysqli->stmt_init();
$backup = new Backup(); // Instancia la clase.
$backup->Statement = $stmt; // Pasa el procedimiento (Ésto es requerido).
$backup->MysqlDatabaseName = $BaseDeDatos; // También es requerido si vas a hacer un respaldo de tu bd.
$backup->Path = ''; // Opcional, no tiene gran importancia, es la ruta dónde se gestionará el fichero zip.
$backup->Name = 'Respaldo'; // Opcional, aquí defines el nombre del backup, de no ser así, se llamará 'Backup' por defecto.
$backup->MysqlBackupName = 'Respaldo-Mysql'; // También opcional, lo mismo que con el nombre, pero con el archivo .sql que se generará dentro de tu zip.
$backup->Init(); // Inicializa el backup DESPUÉS de configurarlo (Requerido).
/*
* Método addTable (string) : void (opcional)
*
* Declara una tabla para luego respaldar sus registros.
*/
$backup->addTable('MiTabla1');
$backup->addTable('MiTabla2');
$backup->addTable('MiTabla3');
/*
* Método generateMysqlBackup () : void (opcional)
*
* Agréga un archivo .sql con el respaldo de todas las tablas mencionadas al fichero .zip.
*/
$backup->generateMysqlBackup();
/*
* Método addFolder (string, string) : void (opcional)
*
* Agrega un directorio completo desde una ruta hacia una carpeta en el .zip
* Parámetro 1 -> De.
* Parámetro 2 -> Hacia.
*
* Parámetro 2 -> RespaldoDirectorio1/Subdirectorio -> Ésto no funcionará.
*/
$backup->addFolder('Directorio1', 'RespladoDirectorio1');
$backup->addFolder('Directorio2', 'RespladoDirectorio2');
/*
* Método SaveAndGet () : void (requerido)
*
* Cierra el .zip y lo pone para descarga, siempre debe ir al final del proceso.
*/
$backup->SaveAndGet();
?>