I have been looking into the user guide which came with CodeIgniter. I became very interested with the dbutil()
method. Particularly the following line of code:
No need to add base_url()
at path
// to intialize the path split the real path by dot .
public function init_path($string){
$array_path = explode('.', $string);
$realpath = '';
foreach ($array_path as $p)
{
$realpath .= $p;
$realpath .= '/';
}
return $realpath;
}
// backup database function
public function archive_database($host = '',$user ='',$pass ='',$name ='', $path = '' , $download_allow = false , $tables=false, $backup_name=false){
$CI = &get_instance();
$CI->load->database();
if($path != '')
{
$path = realpath($this->init_path($path));
}else{
if (!is_dir('archives/'))
mkdir('archives/', 0777);
$path = realpath($this->init_path('archives'));
}
if($host == '')
{
$host = $CI->db->hostname;
}
if($user == '')
{
$user = $CI->db->username;
}
if($pass == '')
{
$pass = $CI->db->password;
}
if($name == '')
{
$name = $CI->db->database;
}
set_time_limit(3000);
$mysqli = new mysqli($host,$user,$pass,$name);
$mysqli->select_db($name);
$mysqli->query("SET NAMES 'utf8'");
$queryTables = $mysqli->query('SHOW TABLES');
while($row = $queryTables->fetch_row()) { $target_tables[] = $row[0]; }
if($tables !== false)
{ $target_tables = array_intersect( $target_tables, $tables); }
$content = "SET SQL_MODE = \"NO_AUTO_VALUE_ON_ZERO\";\r\nSET time_zone = \"+00:00\";\r\n\r\n\r\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;\r\n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;\r\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;\r\n/*!40101 SET NAMES utf8 */;\r\n--\r\n-- Database: `".$name."`\r\n--\r\n\r\n\r\n";
foreach($target_tables as $table){
if (empty($table)){ continue; }
$result = $mysqli->query('SELECT * FROM `'.$table.'`');
$fields_amount=$result->field_count;
$rows_num=$mysqli->affected_rows;
$res = $mysqli->query('SHOW CREATE TABLE '.$table);
$TableMLine=$res->fetch_row();
$content .= "\n\n".$TableMLine[1].";\n\n";
for ($i = 0, $st_counter = 0; $i < $fields_amount; $i++, $st_counter=0) {
while($row = $result->fetch_row()) { //when started (and every after 100 command cycle):
if ($st_counter%100 == 0 || $st_counter == 0 ) {$content .= "\nINSERT INTO ".$table." VALUES";}
$content .= "\n("; for($j=0; $j<$fields_amount; $j++){ $row[$j] = str_replace("\n","\\n", addslashes($row[$j]) ); if (isset($row[$j])){$content .= '"'.$row[$j].'"' ;} else{$content .= '""';} if ($j<($fields_amount-1)){$content.= ',';} } $content .=")";
//every after 100 command cycle [or at last line] ....p.s. but should be inserted 1 cycle eariler
if ( (($st_counter+1)%100==0 && $st_counter!=0) || $st_counter+1==$rows_num) {$content .= ";";} else {$content .= ",";} $st_counter=$st_counter+1;
}
} $content .="\n\n\n";
}
$content .= "\r\n\r\n/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\r\n/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\r\n/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;";
$backup_name = $backup_name ? $backup_name : $name."___(".date('H-i-s')."_".date('d-m-Y').")__rand".rand(1,11111111).".sql";
$fileLocation = $path .'\\'. $backup_name;
$file = fopen($fileLocation,"w");
fwrite($file,$content);
fclose($file);
if($download_allow){
ob_get_clean(); header('Content-Type: application/octet-stream'); header("Content-Transfer-Encoding: Binary"); header("Content-disposition: attachment; filename=\"".$backup_name."\"");
}
echo $content; exit;
}
//load helpers
$this->load->helper('file');
$this->load->helper('download');
$this->load->library('zip');
//load database
$this->load->dbutil();
//create format
$db_format=array('format'=>'zip','filename'=>'backup.sql');
$backup=& $this->dbutil->backup($db_format);
// file name
$dbname='backup-on-'.date('d-m-y H:i').'.zip';
$save='assets/db_backup/'.$dbname;
// write file
write_file($save,$backup);
// and force download
force_download($dbname,$backup);
doing that using php will only work for very small databases. You will very fast run into memory limits - if you increase that other performance problems.
What works best is to create a dump using mysqldump:
header('Content-type: application/force-download');
header('Content-Disposition: attachment; filename="dbbackup.sql.gz"');
passthru("mysqldump --user=xx --host=xx --password=xx dbname | gzip");
of course you must have the required permissions to do that.
If you are lucky enough to have one of the exec()
, shell_exec()
, system()
or passthru()
enabled on your server. Maybe you would want to use the following:
public function db_backup()
{
$DBUSER=$this->db->username;
$DBPASSWD=$this->db->password;
$DATABASE=$this->db->database;
$filename = $DATABASE . "-" . date("Y-m-d_H-i-s") . ".sql.gz";
$mime = "application/x-gzip";
header( "Content-Type: " . $mime );
header( 'Content-Disposition: attachment; filename="' . $filename . '"' );
// $cmd = "mysqldump -u $DBUSER --password=$DBPASSWD $DATABASE | gzip --best";
$cmd = "mysqldump -u $DBUSER --password=$DBPASSWD --no-create-info --complete-insert $DATABASE | gzip --best";
passthru( $cmd );
exit(0);
}
I am extremely new to CodeIgniter but I succeeded to do this backup. Try this, it will work successfully and is very easy to implement. Write the code in your controller and call the function from your view page which use for backup. Get set, go and you are done.
function dbbackup()
{
$this->load->dbutil();
$backup =& $this->dbutil->backup();
$this->load->helper('file');
write_file('<?php echo base_url();?>/downloads', $backup);
$this->load->helper('download');
force_download('mybackup.gz', $backup);
}
For your full application backup, do the same procedure with the following code:
function backup()
{
$this->load->helper('download');
$this->load->library('zip');
$time = time();
$this->zip->read_dir('D:xampp/htdocs/wms/');
$this->zip->download('my_backup.'.$time.'.zip');
}
Here you can use any path of your choice.