Mysqldump database backup through PHP [duplicate] - php
I don't have a basic understanding of how backup of a MySQL database through PHP would work. I have followed one tutorial but it didn't help me understand.
Can someone explain how to create a MySQL backup from PHP?
While you can execute backup commands from PHP, they don't really have anything to do with PHP. It's all about MySQL.
I'd suggest using the mysqldump utility to back up your database. The documentation can be found here : http://dev.mysql.com/doc/refman/5.1/en/mysqldump.html.
The basic usage of mysqldump is
mysqldump -u user_name -p name-of-database >file_to_write_to.sql
You can then restore the backup with a command like
mysql -u user_name -p <file_to_read_from.sql
Do you have access to cron? I'd suggest making a PHP script that runs mysqldump as a cron job. That would be something like
<?php
$filename='database_backup_'.date('G_a_m_d_y').'.sql';
$result=exec('mysqldump database_name --password=your_pass --user=root --single-transaction >/var/backups/'.$filename,$output);
if(empty($output)){/* no output is good */}
else {/* we have something to log the output here*/}
If mysqldump is not available, the article describes another method, using the SELECT INTO OUTFILE and LOAD DATA INFILE commands. The only connection to PHP is that you're using PHP to connect to the database and execute the SQL commands. You could also do this from the command line MySQL program, the MySQL monitor.
It's pretty simple, you're writing an SQL file with one command, and loading/executing it when it's time to restore.
You can find the docs for select into outfile here (just search the page for outfile). LOAD DATA INFILE is essentially the reverse of this. See here for the docs.
Based on the good solution that provided by tazo todua, I've made some of changes since mysql_connect has deprecated and not supported in new php version. I've used mysqli_connect instead and increased the performance of inserting values to the database:
<?php
/**
* Updated: Mohammad M. AlBanna
* Website: MBanna.info
*/
//MySQL server and database
$dbhost = 'localhost';
$dbuser = 'my_user';
$dbpass = 'my_pwd';
$dbname = 'database_name';
$tables = '*';
//Call the core function
backup_tables($dbhost, $dbuser, $dbpass, $dbname, $tables);
//Core function
function backup_tables($host, $user, $pass, $dbname, $tables = '*') {
$link = mysqli_connect($host,$user,$pass, $dbname);
// Check connection
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
exit;
}
mysqli_query($link, "SET NAMES 'utf8'");
//get all of the tables
if($tables == '*')
{
$tables = array();
$result = mysqli_query($link, 'SHOW TABLES');
while($row = mysqli_fetch_row($result))
{
$tables[] = $row[0];
}
}
else
{
$tables = is_array($tables) ? $tables : explode(',',$tables);
}
$return = '';
//cycle through
foreach($tables as $table)
{
$result = mysqli_query($link, 'SELECT * FROM '.$table);
$num_fields = mysqli_num_fields($result);
$num_rows = mysqli_num_rows($result);
$return.= 'DROP TABLE IF EXISTS '.$table.';';
$row2 = mysqli_fetch_row(mysqli_query($link, 'SHOW CREATE TABLE '.$table));
$return.= "\n\n".$row2[1].";\n\n";
$counter = 1;
//Over tables
for ($i = 0; $i < $num_fields; $i++)
{ //Over rows
while($row = mysqli_fetch_row($result))
{
if($counter == 1){
$return.= 'INSERT INTO '.$table.' VALUES(';
} else{
$return.= '(';
}
//Over fields
for($j=0; $j<$num_fields; $j++)
{
$row[$j] = addslashes($row[$j]);
$row[$j] = str_replace("\n","\\n",$row[$j]);
if (isset($row[$j])) { $return.= '"'.$row[$j].'"' ; } else { $return.= '""'; }
if ($j<($num_fields-1)) { $return.= ','; }
}
if($num_rows == $counter){
$return.= ");\n";
} else{
$return.= "),\n";
}
++$counter;
}
}
$return.="\n\n\n";
}
//save file
$fileName = 'db-backup-'.time().'-'.(md5(implode(',',$tables))).'.sql';
$handle = fopen($fileName,'w+');
fwrite($handle,$return);
if(fclose($handle)){
echo "Done, the file name is: ".$fileName;
exit;
}
}
If you want to backup a database from php script you could use a class for example lets call it MySQL. This class will use PDO (build in php class which will handle the connection to the database). This class could look like this:
<?php /*defined in your exampleconfig.php*/
define('DBUSER','root');
define('DBPASS','');
define('SERVERHOST','localhost');
?>
<?php /*defined in examplemyclass.php*/
class MySql{
private $dbc;
private $user;
private $pass;
private $dbname;
private $host;
function __construct($host="localhost", $dbname="your_databse_name_here", $user="your_username", $pass="your_password"){
$this->user = $user;
$this->pass = $pass;
$this->dbname = $dbname;
$this->host = $host;
$opt = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
);
try{
$this->dbc = new PDO('mysql:host='.$this->host.';dbname='.$this->dbname.';charset=utf8', $user, $pass, $opt);
}
catch(PDOException $e){
echo $e->getMessage();
echo "There was a problem with connection to db check credenctials";
}
} /*end function*/
public function backup_tables($tables = '*'){ /* backup the db OR just a table */
$host=$this->host;
$user=$this->user;
$pass=$this->pass;
$dbname=$this->dbname;
$data = "";
//get all of the tables
if($tables == '*')
{
$tables = array();
$result = $this->dbc->prepare('SHOW TABLES');
$result->execute();
while($row = $result->fetch(PDO::FETCH_NUM))
{
$tables[] = $row[0];
}
}
else
{
$tables = is_array($tables) ? $tables : explode(',',$tables);
}
//cycle through
foreach($tables as $table)
{
$resultcount = $this->dbc->prepare('SELECT count(*) FROM '.$table);
$resultcount->execute();
$num_fields = $resultcount->fetch(PDO::FETCH_NUM);
$num_fields = $num_fields[0];
$result = $this->dbc->prepare('SELECT * FROM '.$table);
$result->execute();
$data.= 'DROP TABLE '.$table.';';
$result2 = $this->dbc->prepare('SHOW CREATE TABLE '.$table);
$result2->execute();
$row2 = $result2->fetch(PDO::FETCH_NUM);
$data.= "\n\n".$row2[1].";\n\n";
for ($i = 0; $i < $num_fields; $i++)
{
while($row = $result->fetch(PDO::FETCH_NUM))
{
$data.= 'INSERT INTO '.$table.' VALUES(';
for($j=0; $j<$num_fields; $j++)
{
$row[$j] = addslashes($row[$j]);
$row[$j] = str_replace("\n","\\n",$row[$j]);
if (isset($row[$j])) { $data.= '"'.$row[$j].'"' ; } else { $data.= '""'; }
if ($j<($num_fields-1)) { $data.= ','; }
}
$data.= ");\n";
}
}
$data.="\n\n\n";
}
//save filename
$filename = 'db-backup-'.time().'-'.(implode(",",$tables)).'.sql';
$this->writeUTF8filename($filename,$data);
/*USE EXAMPLE
$connection = new MySql(SERVERHOST,"your_db_name",DBUSER, DBPASS);
$connection->backup_tables(); //OR backup_tables("posts");
$connection->closeConnection();
*/
} /*end function*/
private function writeUTF8filename($filenamename,$content){ /* save as utf8 encoding */
$f=fopen($filenamename,"w+");
# Now UTF-8 - Add byte order mark
fwrite($f, pack("CCC",0xef,0xbb,0xbf));
fwrite($f,$content);
fclose($f);
/*USE EXAMPLE this is only used by public function above...
$this->writeUTF8filename($filename,$data);
*/
} /*end function*/
public function recoverDB($file_to_load){
echo "write some code to load and proccedd .sql file in here ...";
/*USE EXAMPLE this is only used by public function above...
recoverDB("some_buck_up_file.sql");
*/
} /*end function*/
public function closeConnection(){
$this->dbc = null;
//EXAMPLE OF USE
/*$connection->closeConnection();*/
}/*end function*/
} /*END OF CLASS*/
?>
Now you could simply use this in your backup.php:
include ('config.php');
include ('myclass.php');
$connection = new MySql(SERVERHOST,"your_databse_name_here",DBUSER, DBPASS);
$connection->backup_tables(); /*Save all tables and it values in selected database*/
$connection->backup_tables("post_table"); /*Saves only table name posts_table from selected database*/
$connection->closeConnection();
Which means that visiting this page will result in backing up your file... of course it doesn't have to be that way :) you can call this method on every post to your database to be up to date all the time, however, I would recommend to write it to one file at all the time instead of creating new files with time()... as it is above.
Hope it helps and good luck ! :>
Take a look here! It is a native solution written in php. You won't need to exec mysqldump, or cope with incomplete scripts. This is a full mysqldump clone, without dependencies, output compression and sane defaults.
Out of the box, mysqldump-php supports backing up table structures, the data itself, views, triggers and events.
MySQLDump-PHP is the only library that supports:
output binary blobs as hex.
resolves view dependencies (using Stand-In tables).
output compared against original mysqldump. Linked to travis-ci testing system (testing from php 5.3 to 7.1 & hhvm)
dumps stored procedures.
dumps events.
does extended-insert and/or complete-insert.
supports virtual columns from MySQL 5.7.
You can install it using composer, or just download the php file, and it is as easy as doing:
use Ifsnop\Mysqldump as IMysqldump;
try {
$dump = new IMysqldump\Mysqldump('database', 'username', 'password');
$dump->start('storage/work/dump.sql');
} catch (\Exception $e) {
echo 'mysqldump-php error: ' . $e->getMessage();
}
All the options are explained at the github page, but more or less are auto-explicative:
$dumpSettingsDefault = array(
'include-tables' => array(),
'exclude-tables' => array(),
'compress' => Mysqldump::NONE,
'init_commands' => array(),
'no-data' => array(),
'reset-auto-increment' => false,
'add-drop-database' => false,
'add-drop-table' => false,
'add-drop-trigger' => true,
'add-locks' => true,
'complete-insert' => false,
'databases' => false,
'default-character-set' => Mysqldump::UTF8,
'disable-keys' => true,
'extended-insert' => true,
'events' => false,
'hex-blob' => true, /* faster than escaped content */
'net_buffer_length' => self::MAXLINESIZE,
'no-autocommit' => true,
'no-create-info' => false,
'lock-tables' => true,
'routines' => false,
'single-transaction' => true,
'skip-triggers' => false,
'skip-tz-utc' => false,
'skip-comments' => false,
'skip-dump-date' => false,
'skip-definer' => false,
'where' => '',
/* deprecated */
'disable-foreign-keys-check' => true
);
An easy way to do this (output SQL file). To do this, we can use exec or mysqli method
code 1:
example 1 : If you want to back-up a specific database
$database = 'YOUR-DB-NAME';
$user = 'USERNAME';
$pass = 'PASSWORD';
$host = 'localhost';
$dir_1 = dirname(__FILE__) . '/table-'. $database .'.sql';
exec("mysqldump --user={$user} --password={$pass} --host={$host} {$database} --result-file={$dir_1} 2>&1", $output_1);
var_dump($output_1);
example 2 : Backup all database
$user = 'USERNAME';
$pass = 'PASSWORD';
$host = 'localhost';
$dir_2 = dirname(__FILE__) . '/all-database.sql';
exec("mysqldump --user={$user} --password={$pass} --host={$host} --all-databases --result-file={$dir_2} 2>&1", $output_2);
var_dump($output_2);
example 3 : Backup all database and skip lock tables
$user = 'USERNAME';
$pass = 'PASSWORD';
$host = 'localhost';
$dir_3 = dirname(__FILE__) . '/skip-lock-tables.sql';
exec("mysqldump --user={$user} --password={$pass} --host={$host} --all-databases --skip-lock-tables --result-file={$dir_3} 2>&1", $output_3);
var_dump($output_3);
I usually use the following code as well to display errors and warning : Not important
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
Method 2 If you can not activate exec() function. By Mysqli :
<?php
$database = 'YOUR-DB-NAME';
$user = 'USERNAME';
$pass = 'PASSWORD';
$host = 'localhost';
$charset = "utf8mb4"; # utf8mb4_unicode_ci
$conn = new mysqli($host, $user, $pass, $database);
$conn->set_charset($charset);
# get all tables
$result = mysqli_query($conn, "SHOW TABLES");
$tables = array();
while ($row = mysqli_fetch_row($result)) {
$tables[] = $row[0];
}
# Get tables data
$sqlScript = "";
foreach ($tables as $table) {
$query = "SHOW CREATE TABLE $table";
$result = mysqli_query($conn, $query);
$row = mysqli_fetch_row($result);
$sqlScript .= "\n\n" . $row[1] . ";\n\n";
$query = "SELECT * FROM $table";
$result = mysqli_query($conn, $query);
$columnCount = mysqli_num_fields($result);
for ($i = 0; $i < $columnCount; $i ++) {
while ($row = mysqli_fetch_row($result)) {
$sqlScript .= "INSERT INTO $table VALUES(";
for ($j = 0; $j < $columnCount; $j ++) {
$row[$j] = $row[$j];
$sqlScript .= (isset($row[$j])) ? '"' . $row[$j] . '"' : '""';
if ($j < ($columnCount - 1)) {
$sqlScript .= ',';
}
}
$sqlScript .= ");\n";
}
}
$sqlScript .= "\n";
}
//save file
$mysql_file = fopen($database . '_backup_'.time() . '.sql', 'w+');
fwrite($mysql_file ,$sqlScript );
fclose($mysql_file );
From the answer of #DevWL, I got "Undefined offset ..." at
if ($j<($num_fields-1)) { $data.= ','; }
I made some changes to:
preserve relationships (foreign keys)
use Transactions
remove the uneedy $num_fields
class DBbackup {
public $suffix;
public $dirs;
protected $dbInstance;
public function __construct() {
try{
$this->dbInstance = new PDO("mysql:host=".$dbhost.";dbname=".$dbname,
$username, $password);
} catch(Exception $e) {
die("Error ".$e->getMessage());
}
$this->suffix = date('Ymd_His');
}
public function backup($tables = '*'){
$output = "-- database backup - ".date('Y-m-d H:i:s').PHP_EOL;
$output .= "SET NAMES utf8;".PHP_EOL;
$output .= "SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO';".PHP_EOL;
$output .= "SET foreign_key_checks = 0;".PHP_EOL;
$output .= "SET AUTOCOMMIT = 0;".PHP_EOL;
$output .= "START TRANSACTION;".PHP_EOL;
//get all table names
if($tables == '*') {
$tables = [];
$query = $this->dbInstance->prepare('SHOW TABLES');
$query->execute();
while($row = $query->fetch(PDO::FETCH_NUM)) {
$tables[] = $row[0];
}
$query->closeCursor();
}
else {
$tables = is_array($tables) ? $tables : explode(',',$tables);
}
foreach($tables as $table) {
$query = $this->dbInstance->prepare("SELECT * FROM `$table`");
$query->execute();
$output .= "DROP TABLE IF EXISTS `$table`;".PHP_EOL;
$query2 = $this->dbInstance->prepare("SHOW CREATE TABLE `$table`");
$query2->execute();
$row2 = $query2->fetch(PDO::FETCH_NUM);
$query2->closeCursor();
$output .= PHP_EOL.$row2[1].";".PHP_EOL;
while($row = $query->fetch(PDO::FETCH_NUM)) {
$output .= "INSERT INTO `$table` VALUES(";
for($j=0; $j<count($row); $j++) {
$row[$j] = addslashes($row[$j]);
$row[$j] = str_replace("\n","\\n",$row[$j]);
if (isset($row[$j]))
$output .= "'".$row[$j]."'";
else $output .= "''";
if ($j<(count($row)-1))
$output .= ',';
}
$output .= ");".PHP_EOL;
}
}
$output .= PHP_EOL.PHP_EOL;
$output .= "COMMIT;";
//save filename
$filename = 'db_backup_'.$this->suffix.'.sql';
$this->writeUTF8filename($filename,$output);
}
private function writeUTF8filename($fn,$c){ /* save as utf8 encoding */
$f=fopen($fn,"w+");
# Now UTF-8 - Add byte order mark
fwrite($f, pack("CCC",0xef,0xbb,0xbf));
fwrite($f,$c);
fclose($f);
}
}
And usage example:
$Backup = new DBbackup();
$Backup->backup();
This works great on MySQL 10.1.34-MariaDB , PHP : 7.2.7
A solution to take the backup of your Database in "dbBackup" Folder / Directory
<?php
error_reporting(E_ALL);
/* Define database parameters here */
define("DB_USER", 'root');
define("DB_PASSWORD", 'root');
define("DB_NAME", 'YOUR_DATABASE_NAME');
define("DB_HOST", 'localhost');
define("OUTPUT_DIR", 'dbBackup'); // Folder Path / Directory Name
define("TABLES", '*');
/* Instantiate Backup_Database and perform backup */
$backupDatabase = new Backup_Database(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
$status = $backupDatabase->backupTables(TABLES, OUTPUT_DIR) ? 'OK' : 'KO';
echo "Backup result: " . $status;
/* The Backup_Database class */
class Backup_Database {
private $conn;
/* Constructor initializes database */
function __construct( $host, $username, $passwd, $dbName, $charset = 'utf8' ) {
$this->dbName = $dbName;
$this->connectDatabase( $host, $username, $passwd, $charset );
}
protected function connectDatabase( $host, $username, $passwd, $charset ) {
$this->conn = mysqli_connect( $host, $username, $passwd, $this->dbName);
if (mysqli_connect_errno()) {
echo "Failed to connect to MySQL: " . mysqli_connect_error();
exit();
}
/* change character set to $charset Ex : "utf8" */
if (!mysqli_set_charset($this->conn, $charset)) {
printf("Error loading character set ".$charset.": %s\n", mysqli_error($this->conn));
exit();
}
}
/* Backup the whole database or just some tables Use '*' for whole database or 'table1 table2 table3...' #param string $tables */
public function backupTables($tables = '*', $outputDir = '.') {
try {
/* Tables to export */
if ($tables == '*') {
$tables = array();
$result = mysqli_query( $this->conn, 'SHOW TABLES' );
while ( $row = mysqli_fetch_row($result) ) {
$tables[] = $row[0];
}
} else {
$tables = is_array($tables) ? $tables : explode(',', $tables);
}
$sql = 'CREATE DATABASE IF NOT EXISTS ' . $this->dbName . ";\n\n";
$sql .= 'USE ' . $this->dbName . ";\n\n";
/* Iterate tables */
foreach ($tables as $table) {
echo "Backing up " . $table . " table...";
$result = mysqli_query( $this->conn, 'SELECT * FROM ' . $table );
// Return the number of fields in result set
$numFields = mysqli_num_fields($result);
$sql .= 'DROP TABLE IF EXISTS ' . $table . ';';
$row2 = mysqli_fetch_row( mysqli_query( $this->conn, 'SHOW CREATE TABLE ' . $table ) );
$sql.= "\n\n" . $row2[1] . ";\n\n";
for ($i = 0; $i < $numFields; $i++) {
while ($row = mysqli_fetch_row($result)) {
$sql .= 'INSERT INTO ' . $table . ' VALUES(';
for ($j = 0; $j < $numFields; $j++) {
$row[$j] = addslashes($row[$j]);
// $row[$j] = ereg_replace("\n", "\\n", $row[$j]);
if (isset($row[$j])) {
$sql .= '"' . $row[$j] . '"';
} else {
$sql.= '""';
}
if ($j < ($numFields - 1)) {
$sql .= ',';
}
}
$sql.= ");\n";
}
} // End :: for loop
mysqli_free_result($result); // Free result set
$sql.="\n\n\n";
echo " OK <br/>" . "";
}
} catch (Exception $e) {
var_dump($e->getMessage());
return false;
}
return $this->saveFile($sql, $outputDir);
}
/* Save SQL to file #param string $sql */
protected function saveFile(&$sql, $outputDir = '.') {
if (!$sql)
return false;
try {
$handle = fopen($outputDir . '/db-backup-' . $this->dbName . '-' . date("Ymd-His", time()) . '.sql', 'w+');
fwrite($handle, $sql);
fclose($handle);
mysqli_close( $this->conn );
} catch (Exception $e) {
var_dump($e->getMessage());
return false;
}
return true;
}
} // End :: class Backup_Database
?>
for using Cron Job, below is the php function
public function runback() {
$filename = '/var/www/html/local/storage/stores/database_backup_' . date("Y-m-d-H-i-s") . '.sql';
/*
* db backup
*/
$command = "mysqldump --single-transaction -h $dbhost -u$dbuser -p$dbpass yourdb_name > $filename";
system($command);
if ($command == '') {
/* no output is good */
echo 'not done';
} else {
/* we have something to log the output here */
echo 'done';
}
}
There should not be any space between -u and username also no space between -p and password.
CRON JOB command to run this script every sunday 8.30 am:
>> crontab -e
30 8 * * 7 curl -k https://www.websitename.com/takebackup
Try out following example of using SELECT INTO OUTFILE query for creating table backup. This will only backup a particular table.
<?php
$dbhost = 'localhost:3036';
$dbuser = 'root';
$dbpass = 'rootpassword';
$conn = mysql_connect($dbhost, $dbuser, $dbpass);
if(! $conn ) {
die('Could not connect: ' . mysql_error());
}
$table_name = "employee";
$backup_file = "/tmp/employee.sql";
$sql = "SELECT * INTO OUTFILE '$backup_file' FROM $table_name";
mysql_select_db('test_db');
$retval = mysql_query( $sql, $conn );
if(! $retval ) {
die('Could not take data backup: ' . mysql_error());
}
echo "Backedup data successfully\n";
mysql_close($conn);
?>
My very simple backup solution. Each table is saved as a separate file.
<?php
error_reporting(E_ALL);
// set the path to the backup
$bc_dir = dirname(__FILE__).'/back_db/';
// DB-connect settings
$db_user = '';
$db_name = '';
$db_pass = '';
$db_host = 'localhost';
$dsn = 'mysql:dbname='.$db_name.';host='.$db_host.'';
try {
$pdo = new PDO($dsn, $db_user, $db_pass);
} catch (Exception $e) {
var_dump($e->getMessage());
}
$query = $pdo->query('SHOW TABLES');
while ($row = $query->fetch(PDO::FETCH_NUM)) {
exec("mysqldump --user=".$db_user." --password=".$db_pass." --host="
.$db_host." ".$db_name." ".$row[0]." --skip-lock-tables --result-file="
.$bc_dir.$row[0].".sql > /dev/null 2>&1");
}
#T.Todua's answer.
It's cool. However, it failed to backup my database correctly. Hence, I've modified it.
Please use like so: Backup_Mysql_Db::init("localhost","user","pass","db_name","/usr/var/output_dir" );
Thank you.
<?php
/**========================================================+
* +
* Static class with functions for backing up database. +
* +
* PHP Version 5.6.31 +
*=========================================================+*/
class Backup_Mysql_Db
{
private function __construct() {}
/**Initializes the database backup
* #param String $host mysql hostname
* #param String $user mysql user
* #param String $pass mysql password
* #param String $name name of database
* #param String $outputDir the path to the output directory for storing the backup file
* #param Array $tables (optional) to backup specific tables only,like: array("mytable1","mytable2",...)
* #param String $backup_name (optional) backup filename (otherwise, it creates random name)
* EXAMPLE: Backup_Mysql_Db::init("localhost","user","pass","db_name","/usr/var/output_dir" );
*/
public static function init($host,$user,$pass,$name, $outputDir, $tables=false, $backup_name=false)
{
set_time_limit(3000);
$mysqli = new mysqli($host,$user,$pass,$name);
/* check connection */
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
//change database to $name
$mysqli->select_db($name);
/* change character set to utf8 */
if (!$mysqli->set_charset("utf8"))
{
printf("Error loading character set utf8: %s\n", $mysqli->error);
exit();
}
//list all tables in the database
$queryTables = $mysqli->query('SHOW TABLES');
while($row = $queryTables->fetch_row())
{
$target_tables[] = $row[0];
}
//if user opted to backup specific tables only
if($tables !== false)
{
$target_tables = array_intersect( $target_tables, $tables);
}
date_default_timezone_set('Africa/Accra');//set your timezone
//$content is the text data to be written to the file for backup
$content = "-- phpMyAdmin SQL Dump\r\n-- version 4.7.4". //insert your phpMyAdmin version
"\r\n-- https://www.phpmyadmin.net/\r\n--\r\n-- Host: ".$host.
"\r\n-- Generation Time: ".date('M d, Y \a\t h:i A',strtotime(date('Y-m-d H:i:s', time()))).
"\r\n-- Server version: ".$mysqli->server_info.
"\r\n-- PHP Version: ". phpversion();
$content .= "\r\n\r\nSET SQL_MODE = \"NO_AUTO_VALUE_ON_ZERO\";\r\nSET AUTOCOMMIT = 0;\r\nSTART TRANSACTION;\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 utf8mb4 */;\r\n\r\n--\r\n-- Database: `".
$name."`\r\n--\r\nCREATE DATABASE IF NOT EXISTS `".
$name."` DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci;\r\nUSE `".
$name."`;";
//traverse through every table in the database
foreach($target_tables as $table)
{
if (empty($table)){ continue; }
$result = $mysqli->query('SELECT * FROM `'.$table.'`');
//get the number of columns
$fields_amount=$result->field_count;
//get the number of affected rows in the MySQL operation
$rows_num=$mysqli->affected_rows;
//Retrieve the Table Definition of the existing table
$res = $mysqli->query('SHOW CREATE TABLE '.$table);
$TableMLine=$res->fetch_row();
$content .= "\r\n\r\n-- --------------------------------------------------------\r\n\r\n"."--\r\n-- Table structure for table `".$table."`\r\n--\r\n\r\n";
//if the table is not empty
if(!self::table_is_empty($table,$mysqli))
{ $content .= $TableMLine[1].";\n\n";//append the Table Definition
//replace, case insensitively
$content =str_ireplace("CREATE TABLE `".$table."`",//wherever you find this
"DROP TABLE IF EXISTS `".$table."`;\r\nCREATE TABLE IF NOT EXISTS `".$table."`",//replace with that
$content);//in this
$content .= "--\r\n-- Dumping data for table `".$table."`\r\n--\r\n";
$content .= "\nINSERT INTO `".$table."` (".self::get_columns_from_table($table, $mysqli)." ) VALUES\r\n".self::get_values_from_table($table,$mysqli);
}
else//otherwise if the table is empty
{
$content .= $TableMLine[1].";";
//replace, case insensitively
$content =str_ireplace("CREATE TABLE `".$table."`",//wherever you find this
"DROP TABLE IF EXISTS `".$table."`;\r\nCREATE TABLE IF NOT EXISTS `".$table."`",//replace with that
$content);//in this
}
}
$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 */;";
date_default_timezone_set('Africa/Accra');
//format the time at this very moment and get rid of the colon ( windows doesn't allow colons in filenames)
$date = str_replace(":", "-", date('jS M, y. h:i:s A.',strtotime(date('Y-m-d H:i:s', time()))));
//if there's a backup name, use it , otherwise device one
$backup_name = $backup_name ? $backup_name : $name.'___('.$date.').sql';
//Get current buffer contents and delete current output buffer
ob_get_clean();
self::saveFile($content, $backup_name, $outputDir);
exit;
}
/** Save data to file.
* #param String $data The text data to be stored in the file
* #param String $backup_name The name of the backup file
* #param String $outputDir (optional) The directory to save the file to.
* If unspecified, will save in the current directory.
* */
private static function saveFile(&$data,$backup_name, $outputDir = '.')
{
if (!$data)
{
return false;
}
try
{
$handle = fopen($outputDir . '/'. $backup_name , 'w+');
fwrite($handle, $data);
fclose($handle);
} catch (Exception $e)
{
var_dump($e->getMessage());
return false;
}
return true;
}
/**Checks if table is empty
* #param String $table table in mysql database
* #return Boolean true if table is empty, false otherwise
*/
private static function table_is_empty($table,$mysqli)
{
$sql = "SELECT * FROM $table";
$result = mysqli_query($mysqli, $sql);
if($result)
{
if(mysqli_num_rows($result) > 0)
{
return false;
}
else
{
return true;
}
}
return false;
}
/**Retrieves the columns in the table
* #param String $table table in mysql database
* #return String a list of all the columns in the right format
*/
private static function get_columns_from_table($table, $mysqli)
{
$column_header = "";
$result = mysqli_query($mysqli, "SHOW COLUMNS FROM $table");
while($row = $result->fetch_row())
{
$column_header .= "`".$row[0]."`, ";
}
//remove leading and trailing whitespace, and remove the last comma in the string
return rtrim(trim($column_header),',');
}
/**Retrieves the values in the table row by row in the table
* #param String $table table in mysql database
* #return String a list of all the values in the table in the right format
*/
private static function get_values_from_table($table, $mysqli)
{
$values = "";
$columns = [];
//get all the columns in the table
$result = mysqli_query($mysqli, "SHOW COLUMNS FROM $table");
while($row = $result->fetch_row())
{
array_push($columns,$row[0] );
}
$result1 = mysqli_query($mysqli, "SELECT * FROM $table");
//while traversing every row in the table(row by row)
while($row = mysqli_fetch_array($result1))
{ $values .= "(";
//get the values in each column
foreach($columns as $col)
{ //if the value is an Integer
$values .= (self::column_is_of_int_type($table, $col,$mysqli)?
$row["$col"].", "://do not surround it with single quotes
"'".$row["$col"]."', "); //otherwise, surround it with single quotes
}
$values = rtrim(trim($values),','). "),\r\n";
}
return rtrim(trim($values),',').";";
}
/**Checks if the data type in the column is an integer
* #param String $table table in mysql database
* #return Boolean true if it is an integer, false otherwise.
*/
private static function column_is_of_int_type($table, $column,$mysqli)
{
$q = mysqli_query($mysqli,"DESCRIBE $table");
while($row = mysqli_fetch_array($q))
{
if ($column === "{$row['Field']}")
{
if (strpos("{$row['Type']}", 'int') !== false)
{
return true;
}
}
}
return false;
}
}
Related
MySQL replace database
I have a .sql file and want to replace the already existing database by clicking a button. Everything works fine. Except the create query. Is there any query or command to import whole databases? $filename = 'file.sql'; // MySQL host $mysql_host = 'localhost'; // MySQL username $mysql_username = 'user'; // MySQL password $mysql_password = 'pw'; // Database name $mysql_database = 'dbName'; // Connect to MySQL server mysql_connect($mysql_host, $mysql_username, $mysql_password) or die('Error connecting to MySQL server: ' . mysql_error()); // Select database mysql_select_db($mysql_database) or die('Error selecting MySQL database: ' . mysql_error()); $drop_db = "DROP DATABASE dbName"; mysql_query($drop_db) or die ("error"); $create_db = "";
I got it. The solution is to drop the tables not the whole database. function resetClient() { $erg = false; try { // get all tablenames $sql = "SHOW TABLES FROM dbName"; $res = $this->conn->query($sql); $this->conn->query("SET FOREIGN_KEY_CHECKS=0"); // drop all tables in db if (is_object($res)) { if (($res->num_rows > 0)) { while ($row = $res->fetch_row()) { $this->conn->query ("DROP TABLE " . $row[0]); } } } $this->conn->query("SET FOREIGN_KEY_CHECKS=1"); //pause time_nanosleep(0, 250000000); // create tables from script $sql = file_get_contents('./scripts/file.sql'); $this->conn->multi_query($sql); $erg = true; error_log(date("Y-m-d H:i:s")." - DB resetted\n", 3, "./scripts/success.log"); } catch (Exception $e) { // log error_log(date("Y-m-d H:i:s")." - DB error\n" . "resetClientDB() \n" . "Reset error \n" . $e->getMessage() . "\n" , 3, "./scripts/error.log"); } return $erg; }
You could try something like: $cmds=array_filter( file( $filename ) ); foreach( $cmds as $cmd ){ echo $cmd; } If that looks ok substitute the echo for mysql_query( $cmd )... totally untested btw. $sql=array(); $sourcefile='C:\data\db_20101222_0957.sql'; $cmds = file( $sourcefile, FILE_SKIP_EMPTY_LINES | FILE_IGNORE_NEW_LINES ); foreach( $cmds as $cmd ){ if ( substr( $cmd, 0, 2) == '--' || $cmd == '' || substr( $cmd,0, 2)=='/*' ) continue; $sql[]=$cmd; if ( substr( trim( $cmd ), -1, 1 ) == ';' ){ /* Query */ $query=implode( PHP_EOL, $sql ); /* Execute query */ echo '<pre>',$query,'</pre>'; $sql=array(); } }
PDO Insert query in table in another database not working
I want to make a sendmail function on my program. But first, I want to store the information: send_to, subject, and message in a table in another database(mes) where automail is performed. The problem is data fetched from another database(pqap) are not being added on the table(email_queue) in database(mes). In this code, I have a table where all databases in the server are stored. I made a query to select a specific database. $sql5 = "SELECT pl.database, pl.name FROM product_line pl WHERE visible = 1 AND name='PQ AP'"; $dbh = db_connect("mes"); $stmt5 = $dbh->prepare($sql5); $stmt5->execute(); $data = $stmt5->fetchAll(PDO::FETCH_ASSOC); $dbh=null; Then after selecting the database,it has a query for selecting the information in the table on the selected database. Here's the code. foreach ($data as $row5) GenerateEmail($row5['database'], $row5['name']); Then this is part (I think) is not working. I don't know what's the problem. function GenerateEmail($database, $line) { $sql6 = "SELECT * FROM invalid_invoice WHERE ID=:id6"; $dbh = db_connect($database); $stmt6 = $dbh->prepare($sql6); $stmt6->bindParam(':id6', $_POST['idtxt'], PDO::PARAM_INT); $stmt6->execute(); $data = $stmt6->fetchAll(PDO::FETCH_ASSOC); $dbh=null; foreach ($data as $row6) { $invnumb=$row6['Invoice_Number']; $partnumb=$row6['Part_Number']; $issue=$row6['Issues']; $pic=$row6['PIC_Comments']; $emailadd= $row6['PersoninCharge']; if($row6['Status']=="Open") { $message = "<html><b>Invoice Number: {$invnumb}.</b><br><br>"; $message .= "<b>Part Number:</b><br><xmp>{$partnumb}</xmp><br><br>"; $message .= "<b>Issues:</b><br><xmp>{$issue}</xmp><br>"; $message .= "<b>{$pic}<b><br>"; $message .= "</html>"; if(!empty($emailadd)) { dbInsertEmailMessage($emailadd, "Invoice Number: {$invnumb} - {$issue}.", $message); $dbh=null; } } } } function dbInsertEmailMessage($send_to, $subject, $message) { $sql7 = "INSERT INTO email_queue (Send_to, Subject, Message) VALUES (:send_to, :subject, :message)"; $dbh = db_connect("mes"); $stmt7 = $dbh->prepare($sql7); $stmt7->bindParam(':send_to', $send_to, PDO::PARAM_STR); $stmt7->bindParam(':subject', $subject, PDO::PARAM_STR); $stmt7->bindParam(':message', $message, PDO::PARAM_STR); $stmt7->execute(); $dbh=null; } Here's my db connection: function db_connect($DATABASE) { session_start(); // Connection data (server_address, database, username, password) $servername = '*****'; //$namedb = '****'; $userdb = '*****'; $passdb = '*****'; // Display message if successfully connect, otherwise retains and outputs the potential error try { $dbh = new PDO("mysql:host=$servername; dbname=$DATABASE", $userdb, $passdb, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8")); return $dbh; //echo 'Connected to database'; } catch(PDOException $e) { echo $e->getMessage(); } $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); }
There are a couple things that may help with your failed inserts. See if this is what you are looking for, I have notated important points to consider: <?php // take session_start() out of your database connection function // it draws an error when you call it more than once session_start(); // Create a connection class class DBConnect { public function connect($settings = false) { $host = (!empty($settings['host']))? $settings['host'] : false; $username = (!empty($settings['username']))? $settings['username'] : false; $password = (!empty($settings['password']))? $settings['password'] : false; $database = (!empty($settings['database']))? $settings['database'] : false; try { $dbh = new PDO("mysql:host=$host; dbname=$database", $username, $password, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8")); // You return the connection before it hits that setting $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); return $dbh; } catch(PDOException $e) { // Only return the error if an admin is logged in // you may reveal too much about your database on failure return false; //echo $e->getMessage(); } } } // Make a specific connection selector // Put in your database credentials for all your connections function use_db($database = false) { $con = new DBConnect(); if($database == 'mes') return $con->connect(array("database"=>"db1","username"=>"u1","password"=>"p1","host"=>"localhost")); else return $con->connect(array("database"=>"db2","username"=>"u2","password"=>"p2","host"=>"localhost")); } // Create a query class to return selects function query($con,$sql,$bind=false) { if(empty($bind)) $query = $con->query($sql); else { foreach($bind as $key => $value) { $kBind = ":{$key}"; $bindVals[$kBind] = $value; } $query = $con->prepare($sql); $query->execute($bindVals); } while($row = $query->fetch(PDO::FETCH_ASSOC)) { $result[] = $row; } return (!empty($result))? $result:0; } // Create a write function that will write to database function write($con,$sql,$bind=false) { if(empty($bind)) $query = $con->query($sql); else { foreach($bind as $key => $value) { $kBind = ":{$key}"; $bindVals[$kBind] = $value; } $query = $con->prepare($sql); $query->execute($bindVals); } } // Do not create connections in your function(s), rather pass them into the functions // so you can use the same db in and out of functions // Also do not null the connections out function GenerateEmail($con,$conMes,$line = false) { if(empty($_POST['idtxt']) || (!empty($_POST['idtxt']) && !is_numeric($_POST['idtxt']))) return false; $data = query($con,"SELECT * FROM `invalid_invoice` WHERE `ID` = :0", array($_POST['idtxt'])); if($data == 0) return false; // Instead of creating a bunch of inserts, instead create an array // to build multiple rows, then insert only once $i = 0; foreach ($data as $row) { $invnumb = $row['Invoice_Number']; $partnumb = $row['Part_Number']; $issue = $row['Issues']; $pic = $row['PIC_Comments']; $emailadd = $row['PersoninCharge']; if($row['Status']=="Open") { ob_start(); ?><html> <b>Invoice Number: <?php echo $invnumb;?></b><br><br> <b>Part Number:</b><br><xmp><?php echo $partnumb; ?></xmp><br><br> <b>Issues:</b><br><xmp><?php echo $issue; ?></xmp><br> <b><?php echo $pic; ?><b><br> </html> <?php $message = ob_get_contents(); ob_end_clean(); if(!empty($emailadd)) { $bind["{$i}to"] = $emailadd; $bind["{$i}subj"] = "Invoice Number: {$invnumb} - {$issue}."; $bind["{$i}msg"] = htmlspecialchars($message,ENT_QUOTES); $sql[] = "(:{$i}to, :{$i}subj, :{$i}msg)"; } } $i++; } if(!empty($sql)) return dbInsertEmailMessage($conMes,$sql,$bind); return false; } function dbInsertEmailMessage($con,$sql_array,$bind) { if(!is_array($sql_array)) return false; write($con,"INSERT INTO `email_queue` (`Send_to`, `Subject`, `Message`) VALUES ".implode(", ",$sql_array),$bind); return true; } // Create connections $con = use_db(); $conMes = use_db('mes'); GenerateEmail($con,$conMes);
Issues using PHP MySQL Built-In Functions inside a class
I am working with a MySQL Database and having some issues while trying to get data from several built-in PHP MySQL methods. I have written a class to interact with the database, and here are the relevant bits: <?php include("includes/Config.inc.php"); include_once("ChromePHP.class.php"); class Database{ private $db; private $hostname; private $username; private $password; private $schema; function __construct() { if(func_num_args() == 0){ $this->hostname = conf_hostname; $this->username = conf_username; $this->password = conf_password; $this->schema = conf_schema; } else{ $params = func_get_args(); $this->hostname = $params[0]; $this->username = $params[1]; $this->password = $params[2]; $this->schema = $params[3]; } $this->open(); } private function open(){ $this->db = mysql_connect($this->hostname, $this->username, $this->password) or die ('Error connecting to mysql'); mysql_select_db($this->schema, $this->db); mysql_query("SET NAMES utf8"); } public function executeQuery($query){ $results = mysql_query($query, $this->db) or die ("Error in query: $query. ".mysql_error()); return $results; } public function executeNonQuery($query){ mysql_query($query, $this->db) or die ("Error in query: $query. ".mysql_error()); $info = mysql_info($this->db); if($info){ $bits = explode(' ', $info); return $bits[4]; } return false; } public function close(){ mysql_close($this->db); } public function escape($string){ $output = mysql_real_escape_string($string , $this->db); return $output; } public function getRegionTree(){ $query = "SELECT COUNT(parent.Name) - 2 as level, node.Name AS Name, node.ID, node.Parent FROM Region AS node, Region AS parent WHERE node.LeftVal BETWEEN parent.LeftVal AND parent.RightVal and node.Name <> 'Earth' GROUP BY node.ID ORDER BY node.LeftVal"; $result = $this->executeQuery($query); $last_level = 0; $output = '<ul id="regionTree">'.PHP_EOL; while ($row = mysql_fetch_assoc($result)) { $link = '<li>'.PHP_EOL.''.$row["Name"]."".PHP_EOL; $diff = $last_level - $row["level"]; if($diff == 0){ // Sibling $output .= ($row["level"] != 0) ? '</li>'.PHP_EOL.$link:$link; } elseif($diff < 0){ // Child $demoter = '<ul>'.PHP_EOL; for ($i=0; $i > $diff; $i--) { $output .= $demoter; } $output .= $link; } else{ // Parent $promoter = '</li>'.PHP_EOL.'</ul>'; for ($i=0; $i < $diff; $i++) { $output .= ($row["level"] != 0) ? $promoter.PHP_EOL."</li>":$promoter; } $output .= $link; } $last_level = $row["level"]; } $output .= "</li></ul>"; return $output; } public function addRegion($name, $type, $parentID){ $query = "select Name, Region_Type from Region where ID = ".$parentID; $result = $this->executeQuery($query); if($result){ $row = mysql_fetch_assoc($result); $query = "call AddRegion('".$name."', '".$type."', '".$row["Name"]."', '".$row["Region_Type"]."', #returnCode, #returnMessage)"; $result = $this->executeQuery($query); if($result){ return true; } else{ $query = "select #returnCode as code, #returnMessage as message"; $result = $this->executeQuery($query); while($row = mysql_fetch_assoc($result)){ print_r($row); } return false; } } return false; } public function getInfo(){ return mysql_info(); } public function editRegion($id, $name, $type){ $query = "update Region set Name = '$name', Region_Type = '$type' where ID = $id"; if($this->executeNonQuery($query) > 0){ return true; } return false; } } $db = new Database(); ?> With this Database class I am able to successfully make queries, get region trees, and successfully change data in the database using the ExecuteNonQuery function. However, any attempts I have made to use mysql_info, mysql_affected_rows, or other similar functions fails, making it really difficult to write any error handling code. To make matters stranger yet, if I run the following code: <?php $db = mysql_connect("localhost", "User", "Password") or die ('Error connecting to mysql'); mysql_select_db("DB", $db); mysql_query("update Region set Name = 'test' where ID = 594", $db); echo mysql_info($db); ?> I am able to get results as expected. Any Ideas?
Are you using mysql_info and mysql_error outside the Database class? And if so how are you referencing the database connection? If you don't identify the database connection then: The MySQL connection. If the link identifier is not specified, the last link opened by mysql_connect() is assumed. If no such link is found, it will try to create one as if mysql_connect() was called with no arguments. If no connection is found or established, an E_WARNING level error is generated. So internally you should be doing mysql_info($this->db); to get mysql_info. Accessing $db externally requires you to write something to get around it being private. But if you are going to be doing database stuff in an object-oriented mode you really should investigate PDO.
After adding "or die()" statements in several places in my script, I was surprised to see that nothing was actually failing to work, instead it was failing to work the way I expected it to. The problem I was having as it turns out, was that splitting the output of mysql_info (on the space character) resulted in several indices in the array containing nothing, as would be generated by inconsistent whitespace in the output of mysql_info. The index that I thought (based upon counting spaces visually) would contain an integer instead contained a string, and I was attempting to compare that string against the number 0, which won't work. I have updated my executeNonQuery function as follows: public function executeNonQuery($query){ mysql_query($query, $this->db) or die ("Error in query: $query. ".mysql_error()); $info = mysql_info($this->db); if($info){ $output = array(); $bits = explode(' ', $info); $output["rowsMatched"] = $bits[2]; $output["rowsChanged"] = $bits[5]; $output["warnings"] = $bits[8]; return $output; } return false; }
PHP Database Dump Script - are there any issues?
I found a PHP function to dump a mySQL database that someone else had written, and then cleaned it up and formatted it a bit. I wanted to know if I could get a critique of it. I have ran it, tested it on a Wordpress blog and the DB completely restores, but wanted to get some other eyes on the code. Specifically I am looking for feedback on: Anything that could corrupt the data - not properly escaping etc Violating any best practice / principles Security issues Anything else you may see as an issue NOTE: I am NOT looking to use mysqldump, I want to completely generate this sql backup from code. I also realize that the filename could be generated randomly, but the SQL file will be uploaded to dropbox as well, and I want to version it under the same name. Thanks! Code: // Variables $dbHost = 'DBHOST'; $dbUser = 'DBUSER'; $dbPassword = 'DBPASSWORD'; $dbName = 'DBNAME'; $tables = '*'; $fileName = 'mydatabase.sql'; // Logic $link = #mysql_connect($dbHost, $dbUser, $dbPassword); $db = #mysql_select_db($dbName, $link); if(!$link || !$db) die("Database Error"); //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); // Loop through tables foreach($tables as $table) { $result = mysql_query('SELECT * FROM '. $table); $num_fields = mysql_num_fields($result); $return.= 'DROP TABLE IF EXISTS ' . $table . ';'; $createTable = mysql_fetch_row(mysql_query('SHOW CREATE TABLE ' . $table)); $return .= "\n\n" . $createTable[1] . ";\n\n"; for ($i = 0; $i < $num_fields; $i++) { 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] = ereg_replace("\n","\\n", $row[$j]); if (isset($row[$j])) { $return .= '"' . $row[$j] . '"' ; } else { $return .= '""'; } if ($j < ($num_fields-1)) { $return .= ','; } } $return .= ");\n"; } } $return .="\n\n\n"; } // Save the file $handle = fopen($fileName, 'w+'); fwrite($handle, $return); fclose($handle);
That script has serious, deal-breaking problems. It will not work for any but the most trivial database. NULLs are not supported. Character sets are not taken into account. Table names are not delimited. Only tables are supported -- not views, stored procedures, triggers, functions, etc. addslashes() is not character-set safe. mysql_query() pre-fetches all the rows from the table, so if you query a table with millions of rows, you will exceed your PHP memory limit. Use mysql_unbuffered_query() instead. On second thought, I see you collect all the output in $return so this is moot. Your suppression of errors with the # operator is bad practice. Check for errors and fail gracefully with an informative message. Your requirement not to use mysqldump is absurd. Why make so much work for yourself reinventing the wheel, and still get it so wrong? Just run mysqldump via shellexec(). See also: Why is my database backup script not working in php?
Try mysql command or mysqldump command
Character sets? Perhaps SET NAMES utf8 would be a good addition. Also, what happens if the database contains views?
In case this is a very huge database that needs to be dumped, make sure your server (and php max execution memory per script) has enough memory to keep the whole $return in memory, otherwise you better flush to a file once a while, or every line.
This will not dump stored procedures, functions, views, triggers and so on. Edit: You can dump procedures etc. this way too. Just use i.e. SHOW PROCEDURE STATUS; to get the list of procedures and then SHOW CREATE PROCEDURE for each procedure. The same thing for functions, views, triggers... Don't forget SHOW CREATE DATABASE; either.
create backup DB : <?php $dbHost = 'DBHOST'; $dbUser = 'DBUSER'; $dbPassword = 'DBPASSWORD'; $dbName = 'DBNAME'; $tables = '*'; backup_tables($dbHost,$dbUser,$dbPassword,$tables); /* backup the db OR just a table */ function backup_tables($host,$user,$pass,$name,$tables = '*') { $db = new PDO("mysql:host=$host;dbname=$name;", $user, $pass); //get all of the tables if($tables == '*') { $tables = array(); $result = $db->query('SHOW TABLES'); $tables= $result->fetchAll(PDO::FETCH_COLUMN, 0); } else { $tables = is_array($tables) ? $tables : explode(',',$tables); } $return=""; //cycle through foreach($tables as $table) { $return.= 'DROP TABLE IF EXISTS '.$table.';'; $result=$db->query('SHOW CREATE TABLE '.$table); $row2 = $result->fetch(PDO::FETCH_NUM); $return.= "\n\n".$row2[1].";\n\n"; $result = $db->query('SELECT * FROM '.$table); foreach ($result->fetchAll(PDO::FETCH_ASSOC) as $key=>$value) { // build query... $return .= "INSERT INTO $table (`".implode("`, `", array_keys($value))."`) VALUES ('".implode("', '", $value)."');\n\n"; } $return.="\n\n\n"; } //save file $handle = fopen('db-backup-'.date('Y-m-d--H-i-s').'-'.(md5(implode(',',$tables))).'.sql','w+'); fwrite($handle,$return); fclose($handle); }
How to backup MySQL database in PHP?
I don't have a basic understanding of how backup of a MySQL database through PHP would work. I have followed one tutorial but it didn't help me understand. Can someone explain how to create a MySQL backup from PHP?
While you can execute backup commands from PHP, they don't really have anything to do with PHP. It's all about MySQL. I'd suggest using the mysqldump utility to back up your database. The documentation can be found here : http://dev.mysql.com/doc/refman/5.1/en/mysqldump.html. The basic usage of mysqldump is mysqldump -u user_name -p name-of-database >file_to_write_to.sql You can then restore the backup with a command like mysql -u user_name -p <file_to_read_from.sql Do you have access to cron? I'd suggest making a PHP script that runs mysqldump as a cron job. That would be something like <?php $filename='database_backup_'.date('G_a_m_d_y').'.sql'; $result=exec('mysqldump database_name --password=your_pass --user=root --single-transaction >/var/backups/'.$filename,$output); if(empty($output)){/* no output is good */} else {/* we have something to log the output here*/} If mysqldump is not available, the article describes another method, using the SELECT INTO OUTFILE and LOAD DATA INFILE commands. The only connection to PHP is that you're using PHP to connect to the database and execute the SQL commands. You could also do this from the command line MySQL program, the MySQL monitor. It's pretty simple, you're writing an SQL file with one command, and loading/executing it when it's time to restore. You can find the docs for select into outfile here (just search the page for outfile). LOAD DATA INFILE is essentially the reverse of this. See here for the docs.
Based on the good solution that provided by tazo todua, I've made some of changes since mysql_connect has deprecated and not supported in new php version. I've used mysqli_connect instead and increased the performance of inserting values to the database: <?php /** * Updated: Mohammad M. AlBanna * Website: MBanna.info */ //MySQL server and database $dbhost = 'localhost'; $dbuser = 'my_user'; $dbpass = 'my_pwd'; $dbname = 'database_name'; $tables = '*'; //Call the core function backup_tables($dbhost, $dbuser, $dbpass, $dbname, $tables); //Core function function backup_tables($host, $user, $pass, $dbname, $tables = '*') { $link = mysqli_connect($host,$user,$pass, $dbname); // Check connection if (mysqli_connect_errno()) { echo "Failed to connect to MySQL: " . mysqli_connect_error(); exit; } mysqli_query($link, "SET NAMES 'utf8'"); //get all of the tables if($tables == '*') { $tables = array(); $result = mysqli_query($link, 'SHOW TABLES'); while($row = mysqli_fetch_row($result)) { $tables[] = $row[0]; } } else { $tables = is_array($tables) ? $tables : explode(',',$tables); } $return = ''; //cycle through foreach($tables as $table) { $result = mysqli_query($link, 'SELECT * FROM '.$table); $num_fields = mysqli_num_fields($result); $num_rows = mysqli_num_rows($result); $return.= 'DROP TABLE IF EXISTS '.$table.';'; $row2 = mysqli_fetch_row(mysqli_query($link, 'SHOW CREATE TABLE '.$table)); $return.= "\n\n".$row2[1].";\n\n"; $counter = 1; //Over tables for ($i = 0; $i < $num_fields; $i++) { //Over rows while($row = mysqli_fetch_row($result)) { if($counter == 1){ $return.= 'INSERT INTO '.$table.' VALUES('; } else{ $return.= '('; } //Over fields for($j=0; $j<$num_fields; $j++) { $row[$j] = addslashes($row[$j]); $row[$j] = str_replace("\n","\\n",$row[$j]); if (isset($row[$j])) { $return.= '"'.$row[$j].'"' ; } else { $return.= '""'; } if ($j<($num_fields-1)) { $return.= ','; } } if($num_rows == $counter){ $return.= ");\n"; } else{ $return.= "),\n"; } ++$counter; } } $return.="\n\n\n"; } //save file $fileName = 'db-backup-'.time().'-'.(md5(implode(',',$tables))).'.sql'; $handle = fopen($fileName,'w+'); fwrite($handle,$return); if(fclose($handle)){ echo "Done, the file name is: ".$fileName; exit; } }
If you want to backup a database from php script you could use a class for example lets call it MySQL. This class will use PDO (build in php class which will handle the connection to the database). This class could look like this: <?php /*defined in your exampleconfig.php*/ define('DBUSER','root'); define('DBPASS',''); define('SERVERHOST','localhost'); ?> <?php /*defined in examplemyclass.php*/ class MySql{ private $dbc; private $user; private $pass; private $dbname; private $host; function __construct($host="localhost", $dbname="your_databse_name_here", $user="your_username", $pass="your_password"){ $this->user = $user; $this->pass = $pass; $this->dbname = $dbname; $this->host = $host; $opt = array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ); try{ $this->dbc = new PDO('mysql:host='.$this->host.';dbname='.$this->dbname.';charset=utf8', $user, $pass, $opt); } catch(PDOException $e){ echo $e->getMessage(); echo "There was a problem with connection to db check credenctials"; } } /*end function*/ public function backup_tables($tables = '*'){ /* backup the db OR just a table */ $host=$this->host; $user=$this->user; $pass=$this->pass; $dbname=$this->dbname; $data = ""; //get all of the tables if($tables == '*') { $tables = array(); $result = $this->dbc->prepare('SHOW TABLES'); $result->execute(); while($row = $result->fetch(PDO::FETCH_NUM)) { $tables[] = $row[0]; } } else { $tables = is_array($tables) ? $tables : explode(',',$tables); } //cycle through foreach($tables as $table) { $resultcount = $this->dbc->prepare('SELECT count(*) FROM '.$table); $resultcount->execute(); $num_fields = $resultcount->fetch(PDO::FETCH_NUM); $num_fields = $num_fields[0]; $result = $this->dbc->prepare('SELECT * FROM '.$table); $result->execute(); $data.= 'DROP TABLE '.$table.';'; $result2 = $this->dbc->prepare('SHOW CREATE TABLE '.$table); $result2->execute(); $row2 = $result2->fetch(PDO::FETCH_NUM); $data.= "\n\n".$row2[1].";\n\n"; for ($i = 0; $i < $num_fields; $i++) { while($row = $result->fetch(PDO::FETCH_NUM)) { $data.= 'INSERT INTO '.$table.' VALUES('; for($j=0; $j<$num_fields; $j++) { $row[$j] = addslashes($row[$j]); $row[$j] = str_replace("\n","\\n",$row[$j]); if (isset($row[$j])) { $data.= '"'.$row[$j].'"' ; } else { $data.= '""'; } if ($j<($num_fields-1)) { $data.= ','; } } $data.= ");\n"; } } $data.="\n\n\n"; } //save filename $filename = 'db-backup-'.time().'-'.(implode(",",$tables)).'.sql'; $this->writeUTF8filename($filename,$data); /*USE EXAMPLE $connection = new MySql(SERVERHOST,"your_db_name",DBUSER, DBPASS); $connection->backup_tables(); //OR backup_tables("posts"); $connection->closeConnection(); */ } /*end function*/ private function writeUTF8filename($filenamename,$content){ /* save as utf8 encoding */ $f=fopen($filenamename,"w+"); # Now UTF-8 - Add byte order mark fwrite($f, pack("CCC",0xef,0xbb,0xbf)); fwrite($f,$content); fclose($f); /*USE EXAMPLE this is only used by public function above... $this->writeUTF8filename($filename,$data); */ } /*end function*/ public function recoverDB($file_to_load){ echo "write some code to load and proccedd .sql file in here ..."; /*USE EXAMPLE this is only used by public function above... recoverDB("some_buck_up_file.sql"); */ } /*end function*/ public function closeConnection(){ $this->dbc = null; //EXAMPLE OF USE /*$connection->closeConnection();*/ }/*end function*/ } /*END OF CLASS*/ ?> Now you could simply use this in your backup.php: include ('config.php'); include ('myclass.php'); $connection = new MySql(SERVERHOST,"your_databse_name_here",DBUSER, DBPASS); $connection->backup_tables(); /*Save all tables and it values in selected database*/ $connection->backup_tables("post_table"); /*Saves only table name posts_table from selected database*/ $connection->closeConnection(); Which means that visiting this page will result in backing up your file... of course it doesn't have to be that way :) you can call this method on every post to your database to be up to date all the time, however, I would recommend to write it to one file at all the time instead of creating new files with time()... as it is above. Hope it helps and good luck ! :>
Take a look here! It is a native solution written in php. You won't need to exec mysqldump, or cope with incomplete scripts. This is a full mysqldump clone, without dependencies, output compression and sane defaults. Out of the box, mysqldump-php supports backing up table structures, the data itself, views, triggers and events. MySQLDump-PHP is the only library that supports: output binary blobs as hex. resolves view dependencies (using Stand-In tables). output compared against original mysqldump. Linked to travis-ci testing system (testing from php 5.3 to 7.1 & hhvm) dumps stored procedures. dumps events. does extended-insert and/or complete-insert. supports virtual columns from MySQL 5.7. You can install it using composer, or just download the php file, and it is as easy as doing: use Ifsnop\Mysqldump as IMysqldump; try { $dump = new IMysqldump\Mysqldump('database', 'username', 'password'); $dump->start('storage/work/dump.sql'); } catch (\Exception $e) { echo 'mysqldump-php error: ' . $e->getMessage(); } All the options are explained at the github page, but more or less are auto-explicative: $dumpSettingsDefault = array( 'include-tables' => array(), 'exclude-tables' => array(), 'compress' => Mysqldump::NONE, 'init_commands' => array(), 'no-data' => array(), 'reset-auto-increment' => false, 'add-drop-database' => false, 'add-drop-table' => false, 'add-drop-trigger' => true, 'add-locks' => true, 'complete-insert' => false, 'databases' => false, 'default-character-set' => Mysqldump::UTF8, 'disable-keys' => true, 'extended-insert' => true, 'events' => false, 'hex-blob' => true, /* faster than escaped content */ 'net_buffer_length' => self::MAXLINESIZE, 'no-autocommit' => true, 'no-create-info' => false, 'lock-tables' => true, 'routines' => false, 'single-transaction' => true, 'skip-triggers' => false, 'skip-tz-utc' => false, 'skip-comments' => false, 'skip-dump-date' => false, 'skip-definer' => false, 'where' => '', /* deprecated */ 'disable-foreign-keys-check' => true );
An easy way to do this (output SQL file). To do this, we can use exec or mysqli method code 1: example 1 : If you want to back-up a specific database $database = 'YOUR-DB-NAME'; $user = 'USERNAME'; $pass = 'PASSWORD'; $host = 'localhost'; $dir_1 = dirname(__FILE__) . '/table-'. $database .'.sql'; exec("mysqldump --user={$user} --password={$pass} --host={$host} {$database} --result-file={$dir_1} 2>&1", $output_1); var_dump($output_1); example 2 : Backup all database $user = 'USERNAME'; $pass = 'PASSWORD'; $host = 'localhost'; $dir_2 = dirname(__FILE__) . '/all-database.sql'; exec("mysqldump --user={$user} --password={$pass} --host={$host} --all-databases --result-file={$dir_2} 2>&1", $output_2); var_dump($output_2); example 3 : Backup all database and skip lock tables $user = 'USERNAME'; $pass = 'PASSWORD'; $host = 'localhost'; $dir_3 = dirname(__FILE__) . '/skip-lock-tables.sql'; exec("mysqldump --user={$user} --password={$pass} --host={$host} --all-databases --skip-lock-tables --result-file={$dir_3} 2>&1", $output_3); var_dump($output_3); I usually use the following code as well to display errors and warning : Not important ini_set('display_errors', 1); ini_set('display_startup_errors', 1); error_reporting(E_ALL); Method 2 If you can not activate exec() function. By Mysqli : <?php $database = 'YOUR-DB-NAME'; $user = 'USERNAME'; $pass = 'PASSWORD'; $host = 'localhost'; $charset = "utf8mb4"; # utf8mb4_unicode_ci $conn = new mysqli($host, $user, $pass, $database); $conn->set_charset($charset); # get all tables $result = mysqli_query($conn, "SHOW TABLES"); $tables = array(); while ($row = mysqli_fetch_row($result)) { $tables[] = $row[0]; } # Get tables data $sqlScript = ""; foreach ($tables as $table) { $query = "SHOW CREATE TABLE $table"; $result = mysqli_query($conn, $query); $row = mysqli_fetch_row($result); $sqlScript .= "\n\n" . $row[1] . ";\n\n"; $query = "SELECT * FROM $table"; $result = mysqli_query($conn, $query); $columnCount = mysqli_num_fields($result); for ($i = 0; $i < $columnCount; $i ++) { while ($row = mysqli_fetch_row($result)) { $sqlScript .= "INSERT INTO $table VALUES("; for ($j = 0; $j < $columnCount; $j ++) { $row[$j] = $row[$j]; $sqlScript .= (isset($row[$j])) ? '"' . $row[$j] . '"' : '""'; if ($j < ($columnCount - 1)) { $sqlScript .= ','; } } $sqlScript .= ");\n"; } } $sqlScript .= "\n"; } //save file $mysql_file = fopen($database . '_backup_'.time() . '.sql', 'w+'); fwrite($mysql_file ,$sqlScript ); fclose($mysql_file );
From the answer of #DevWL, I got "Undefined offset ..." at if ($j<($num_fields-1)) { $data.= ','; } I made some changes to: preserve relationships (foreign keys) use Transactions remove the uneedy $num_fields class DBbackup { public $suffix; public $dirs; protected $dbInstance; public function __construct() { try{ $this->dbInstance = new PDO("mysql:host=".$dbhost.";dbname=".$dbname, $username, $password); } catch(Exception $e) { die("Error ".$e->getMessage()); } $this->suffix = date('Ymd_His'); } public function backup($tables = '*'){ $output = "-- database backup - ".date('Y-m-d H:i:s').PHP_EOL; $output .= "SET NAMES utf8;".PHP_EOL; $output .= "SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO';".PHP_EOL; $output .= "SET foreign_key_checks = 0;".PHP_EOL; $output .= "SET AUTOCOMMIT = 0;".PHP_EOL; $output .= "START TRANSACTION;".PHP_EOL; //get all table names if($tables == '*') { $tables = []; $query = $this->dbInstance->prepare('SHOW TABLES'); $query->execute(); while($row = $query->fetch(PDO::FETCH_NUM)) { $tables[] = $row[0]; } $query->closeCursor(); } else { $tables = is_array($tables) ? $tables : explode(',',$tables); } foreach($tables as $table) { $query = $this->dbInstance->prepare("SELECT * FROM `$table`"); $query->execute(); $output .= "DROP TABLE IF EXISTS `$table`;".PHP_EOL; $query2 = $this->dbInstance->prepare("SHOW CREATE TABLE `$table`"); $query2->execute(); $row2 = $query2->fetch(PDO::FETCH_NUM); $query2->closeCursor(); $output .= PHP_EOL.$row2[1].";".PHP_EOL; while($row = $query->fetch(PDO::FETCH_NUM)) { $output .= "INSERT INTO `$table` VALUES("; for($j=0; $j<count($row); $j++) { $row[$j] = addslashes($row[$j]); $row[$j] = str_replace("\n","\\n",$row[$j]); if (isset($row[$j])) $output .= "'".$row[$j]."'"; else $output .= "''"; if ($j<(count($row)-1)) $output .= ','; } $output .= ");".PHP_EOL; } } $output .= PHP_EOL.PHP_EOL; $output .= "COMMIT;"; //save filename $filename = 'db_backup_'.$this->suffix.'.sql'; $this->writeUTF8filename($filename,$output); } private function writeUTF8filename($fn,$c){ /* save as utf8 encoding */ $f=fopen($fn,"w+"); # Now UTF-8 - Add byte order mark fwrite($f, pack("CCC",0xef,0xbb,0xbf)); fwrite($f,$c); fclose($f); } } And usage example: $Backup = new DBbackup(); $Backup->backup(); This works great on MySQL 10.1.34-MariaDB , PHP : 7.2.7
A solution to take the backup of your Database in "dbBackup" Folder / Directory <?php error_reporting(E_ALL); /* Define database parameters here */ define("DB_USER", 'root'); define("DB_PASSWORD", 'root'); define("DB_NAME", 'YOUR_DATABASE_NAME'); define("DB_HOST", 'localhost'); define("OUTPUT_DIR", 'dbBackup'); // Folder Path / Directory Name define("TABLES", '*'); /* Instantiate Backup_Database and perform backup */ $backupDatabase = new Backup_Database(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME); $status = $backupDatabase->backupTables(TABLES, OUTPUT_DIR) ? 'OK' : 'KO'; echo "Backup result: " . $status; /* The Backup_Database class */ class Backup_Database { private $conn; /* Constructor initializes database */ function __construct( $host, $username, $passwd, $dbName, $charset = 'utf8' ) { $this->dbName = $dbName; $this->connectDatabase( $host, $username, $passwd, $charset ); } protected function connectDatabase( $host, $username, $passwd, $charset ) { $this->conn = mysqli_connect( $host, $username, $passwd, $this->dbName); if (mysqli_connect_errno()) { echo "Failed to connect to MySQL: " . mysqli_connect_error(); exit(); } /* change character set to $charset Ex : "utf8" */ if (!mysqli_set_charset($this->conn, $charset)) { printf("Error loading character set ".$charset.": %s\n", mysqli_error($this->conn)); exit(); } } /* Backup the whole database or just some tables Use '*' for whole database or 'table1 table2 table3...' #param string $tables */ public function backupTables($tables = '*', $outputDir = '.') { try { /* Tables to export */ if ($tables == '*') { $tables = array(); $result = mysqli_query( $this->conn, 'SHOW TABLES' ); while ( $row = mysqli_fetch_row($result) ) { $tables[] = $row[0]; } } else { $tables = is_array($tables) ? $tables : explode(',', $tables); } $sql = 'CREATE DATABASE IF NOT EXISTS ' . $this->dbName . ";\n\n"; $sql .= 'USE ' . $this->dbName . ";\n\n"; /* Iterate tables */ foreach ($tables as $table) { echo "Backing up " . $table . " table..."; $result = mysqli_query( $this->conn, 'SELECT * FROM ' . $table ); // Return the number of fields in result set $numFields = mysqli_num_fields($result); $sql .= 'DROP TABLE IF EXISTS ' . $table . ';'; $row2 = mysqli_fetch_row( mysqli_query( $this->conn, 'SHOW CREATE TABLE ' . $table ) ); $sql.= "\n\n" . $row2[1] . ";\n\n"; for ($i = 0; $i < $numFields; $i++) { while ($row = mysqli_fetch_row($result)) { $sql .= 'INSERT INTO ' . $table . ' VALUES('; for ($j = 0; $j < $numFields; $j++) { $row[$j] = addslashes($row[$j]); // $row[$j] = ereg_replace("\n", "\\n", $row[$j]); if (isset($row[$j])) { $sql .= '"' . $row[$j] . '"'; } else { $sql.= '""'; } if ($j < ($numFields - 1)) { $sql .= ','; } } $sql.= ");\n"; } } // End :: for loop mysqli_free_result($result); // Free result set $sql.="\n\n\n"; echo " OK <br/>" . ""; } } catch (Exception $e) { var_dump($e->getMessage()); return false; } return $this->saveFile($sql, $outputDir); } /* Save SQL to file #param string $sql */ protected function saveFile(&$sql, $outputDir = '.') { if (!$sql) return false; try { $handle = fopen($outputDir . '/db-backup-' . $this->dbName . '-' . date("Ymd-His", time()) . '.sql', 'w+'); fwrite($handle, $sql); fclose($handle); mysqli_close( $this->conn ); } catch (Exception $e) { var_dump($e->getMessage()); return false; } return true; } } // End :: class Backup_Database ?>
for using Cron Job, below is the php function public function runback() { $filename = '/var/www/html/local/storage/stores/database_backup_' . date("Y-m-d-H-i-s") . '.sql'; /* * db backup */ $command = "mysqldump --single-transaction -h $dbhost -u$dbuser -p$dbpass yourdb_name > $filename"; system($command); if ($command == '') { /* no output is good */ echo 'not done'; } else { /* we have something to log the output here */ echo 'done'; } } There should not be any space between -u and username also no space between -p and password. CRON JOB command to run this script every sunday 8.30 am: >> crontab -e 30 8 * * 7 curl -k https://www.websitename.com/takebackup
Try out following example of using SELECT INTO OUTFILE query for creating table backup. This will only backup a particular table. <?php $dbhost = 'localhost:3036'; $dbuser = 'root'; $dbpass = 'rootpassword'; $conn = mysql_connect($dbhost, $dbuser, $dbpass); if(! $conn ) { die('Could not connect: ' . mysql_error()); } $table_name = "employee"; $backup_file = "/tmp/employee.sql"; $sql = "SELECT * INTO OUTFILE '$backup_file' FROM $table_name"; mysql_select_db('test_db'); $retval = mysql_query( $sql, $conn ); if(! $retval ) { die('Could not take data backup: ' . mysql_error()); } echo "Backedup data successfully\n"; mysql_close($conn); ?>
My very simple backup solution. Each table is saved as a separate file. <?php error_reporting(E_ALL); // set the path to the backup $bc_dir = dirname(__FILE__).'/back_db/'; // DB-connect settings $db_user = ''; $db_name = ''; $db_pass = ''; $db_host = 'localhost'; $dsn = 'mysql:dbname='.$db_name.';host='.$db_host.''; try { $pdo = new PDO($dsn, $db_user, $db_pass); } catch (Exception $e) { var_dump($e->getMessage()); } $query = $pdo->query('SHOW TABLES'); while ($row = $query->fetch(PDO::FETCH_NUM)) { exec("mysqldump --user=".$db_user." --password=".$db_pass." --host=" .$db_host." ".$db_name." ".$row[0]." --skip-lock-tables --result-file=" .$bc_dir.$row[0].".sql > /dev/null 2>&1"); }
#T.Todua's answer. It's cool. However, it failed to backup my database correctly. Hence, I've modified it. Please use like so: Backup_Mysql_Db::init("localhost","user","pass","db_name","/usr/var/output_dir" ); Thank you. <?php /**========================================================+ * + * Static class with functions for backing up database. + * + * PHP Version 5.6.31 + *=========================================================+*/ class Backup_Mysql_Db { private function __construct() {} /**Initializes the database backup * #param String $host mysql hostname * #param String $user mysql user * #param String $pass mysql password * #param String $name name of database * #param String $outputDir the path to the output directory for storing the backup file * #param Array $tables (optional) to backup specific tables only,like: array("mytable1","mytable2",...) * #param String $backup_name (optional) backup filename (otherwise, it creates random name) * EXAMPLE: Backup_Mysql_Db::init("localhost","user","pass","db_name","/usr/var/output_dir" ); */ public static function init($host,$user,$pass,$name, $outputDir, $tables=false, $backup_name=false) { set_time_limit(3000); $mysqli = new mysqli($host,$user,$pass,$name); /* check connection */ if (mysqli_connect_errno()) { printf("Connect failed: %s\n", mysqli_connect_error()); exit(); } //change database to $name $mysqli->select_db($name); /* change character set to utf8 */ if (!$mysqli->set_charset("utf8")) { printf("Error loading character set utf8: %s\n", $mysqli->error); exit(); } //list all tables in the database $queryTables = $mysqli->query('SHOW TABLES'); while($row = $queryTables->fetch_row()) { $target_tables[] = $row[0]; } //if user opted to backup specific tables only if($tables !== false) { $target_tables = array_intersect( $target_tables, $tables); } date_default_timezone_set('Africa/Accra');//set your timezone //$content is the text data to be written to the file for backup $content = "-- phpMyAdmin SQL Dump\r\n-- version 4.7.4". //insert your phpMyAdmin version "\r\n-- https://www.phpmyadmin.net/\r\n--\r\n-- Host: ".$host. "\r\n-- Generation Time: ".date('M d, Y \a\t h:i A',strtotime(date('Y-m-d H:i:s', time()))). "\r\n-- Server version: ".$mysqli->server_info. "\r\n-- PHP Version: ". phpversion(); $content .= "\r\n\r\nSET SQL_MODE = \"NO_AUTO_VALUE_ON_ZERO\";\r\nSET AUTOCOMMIT = 0;\r\nSTART TRANSACTION;\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 utf8mb4 */;\r\n\r\n--\r\n-- Database: `". $name."`\r\n--\r\nCREATE DATABASE IF NOT EXISTS `". $name."` DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci;\r\nUSE `". $name."`;"; //traverse through every table in the database foreach($target_tables as $table) { if (empty($table)){ continue; } $result = $mysqli->query('SELECT * FROM `'.$table.'`'); //get the number of columns $fields_amount=$result->field_count; //get the number of affected rows in the MySQL operation $rows_num=$mysqli->affected_rows; //Retrieve the Table Definition of the existing table $res = $mysqli->query('SHOW CREATE TABLE '.$table); $TableMLine=$res->fetch_row(); $content .= "\r\n\r\n-- --------------------------------------------------------\r\n\r\n"."--\r\n-- Table structure for table `".$table."`\r\n--\r\n\r\n"; //if the table is not empty if(!self::table_is_empty($table,$mysqli)) { $content .= $TableMLine[1].";\n\n";//append the Table Definition //replace, case insensitively $content =str_ireplace("CREATE TABLE `".$table."`",//wherever you find this "DROP TABLE IF EXISTS `".$table."`;\r\nCREATE TABLE IF NOT EXISTS `".$table."`",//replace with that $content);//in this $content .= "--\r\n-- Dumping data for table `".$table."`\r\n--\r\n"; $content .= "\nINSERT INTO `".$table."` (".self::get_columns_from_table($table, $mysqli)." ) VALUES\r\n".self::get_values_from_table($table,$mysqli); } else//otherwise if the table is empty { $content .= $TableMLine[1].";"; //replace, case insensitively $content =str_ireplace("CREATE TABLE `".$table."`",//wherever you find this "DROP TABLE IF EXISTS `".$table."`;\r\nCREATE TABLE IF NOT EXISTS `".$table."`",//replace with that $content);//in this } } $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 */;"; date_default_timezone_set('Africa/Accra'); //format the time at this very moment and get rid of the colon ( windows doesn't allow colons in filenames) $date = str_replace(":", "-", date('jS M, y. h:i:s A.',strtotime(date('Y-m-d H:i:s', time())))); //if there's a backup name, use it , otherwise device one $backup_name = $backup_name ? $backup_name : $name.'___('.$date.').sql'; //Get current buffer contents and delete current output buffer ob_get_clean(); self::saveFile($content, $backup_name, $outputDir); exit; } /** Save data to file. * #param String $data The text data to be stored in the file * #param String $backup_name The name of the backup file * #param String $outputDir (optional) The directory to save the file to. * If unspecified, will save in the current directory. * */ private static function saveFile(&$data,$backup_name, $outputDir = '.') { if (!$data) { return false; } try { $handle = fopen($outputDir . '/'. $backup_name , 'w+'); fwrite($handle, $data); fclose($handle); } catch (Exception $e) { var_dump($e->getMessage()); return false; } return true; } /**Checks if table is empty * #param String $table table in mysql database * #return Boolean true if table is empty, false otherwise */ private static function table_is_empty($table,$mysqli) { $sql = "SELECT * FROM $table"; $result = mysqli_query($mysqli, $sql); if($result) { if(mysqli_num_rows($result) > 0) { return false; } else { return true; } } return false; } /**Retrieves the columns in the table * #param String $table table in mysql database * #return String a list of all the columns in the right format */ private static function get_columns_from_table($table, $mysqli) { $column_header = ""; $result = mysqli_query($mysqli, "SHOW COLUMNS FROM $table"); while($row = $result->fetch_row()) { $column_header .= "`".$row[0]."`, "; } //remove leading and trailing whitespace, and remove the last comma in the string return rtrim(trim($column_header),','); } /**Retrieves the values in the table row by row in the table * #param String $table table in mysql database * #return String a list of all the values in the table in the right format */ private static function get_values_from_table($table, $mysqli) { $values = ""; $columns = []; //get all the columns in the table $result = mysqli_query($mysqli, "SHOW COLUMNS FROM $table"); while($row = $result->fetch_row()) { array_push($columns,$row[0] ); } $result1 = mysqli_query($mysqli, "SELECT * FROM $table"); //while traversing every row in the table(row by row) while($row = mysqli_fetch_array($result1)) { $values .= "("; //get the values in each column foreach($columns as $col) { //if the value is an Integer $values .= (self::column_is_of_int_type($table, $col,$mysqli)? $row["$col"].", "://do not surround it with single quotes "'".$row["$col"]."', "); //otherwise, surround it with single quotes } $values = rtrim(trim($values),','). "),\r\n"; } return rtrim(trim($values),',').";"; } /**Checks if the data type in the column is an integer * #param String $table table in mysql database * #return Boolean true if it is an integer, false otherwise. */ private static function column_is_of_int_type($table, $column,$mysqli) { $q = mysqli_query($mysqli,"DESCRIBE $table"); while($row = mysqli_fetch_array($q)) { if ($column === "{$row['Field']}") { if (strpos("{$row['Type']}", 'int') !== false) { return true; } } } return false; } }