Fazer o backup do banco de dados é uma tarefa essencial para recuperar o sistema após um crash de hardware, ataque hacker, invasão alienígena etc...
Pensando nisso estou colocando nas minhas aplicações um botão de backup para que o usuário final possa fazer ele mesmo um backup do banco de dados e salvar em um Pendrive, mandar por e-mail para ele mesmo, ou mandar imprimir em formulário contínuo pra ver se chega na lua, sei lá.
Procurei um bom tanto na internet não achei algo que fosse 100% o que eu queria mas achei algo próximo que me ajudou a lot em http://www.devmedia.com.br/post-3925-Fazendo-backup-de-Mysql-atraves-de-PHP.html
Problema: se um usuário colocasse uma string com um ' no meio, ele fecha a string do sql que usa ' para delimitar a string.
Para isso escapamos as single-quotes ou aspas simples ' com um backslash ou barra invertida \ antes.
Um erro parecido acontece se no banco houver uma string que termina com backslash, pois isso anularia a single quote que fecha a string, então antes de backslash, deve-se colocar outro backslash.
Sem entrar em maiores detalhes sobre ordem dos fatores fiz uma outra adção para quem usa UTF-8 e quer validar os caracteres, erros com importações mal feitas podem ocasionar alguns erros na geração do script esse $checkUtf, se true remove caracteres que não sejam UTF-8 evitando esse pau.
Segue o código, com certeza aceito comentários e sugestões de melhoria.
<?php
// código baseado em http://www.devmedia.com.br/post-3925-Fazendo-backup-de-Mysql-atraves-de-PHP.html
// com melhorias dos comentários do mesmo post
// com adicional de escape string por Marcos Fedato marcosfedato.blogspot.com.br
// com checagem de caracteres UTF-8 por http://stackoverflow.com/questions/1401317/remove-non-utf8-characters-from-string
$usuario = "user";
$senha = "123";
$dbname = "mydb";
// use true se quiser remover caracteres que não sejam utf-8
$checkUtf = false;
// conectando ao banco
mysql_connect("localhost", $usuario, $senha) or die(mysql_error());
mysql_select_db($dbname) or die(mysql_error());
// gerando um arquivo sql. Como?
// a função fopen, abre um arquivo, que no meu caso, será chamado como: nomedobanco.sql
// note que eu estou concatenando dinamicamente o nome do banco com a extensão .sql.
$back = fopen($dbname . ".sql", "w");
// aqui, listo todas as tabelas daquele banco selecionado acima
$res = mysql_list_tables($dbname) or die(mysql_error());
// ultra importante para não dar erro nos primeiros inserts
// principalmente de usar InnoDB e relacionar as tabelas
fwrite($back, "set foreign_key_checks=0;\n\n");
// regex para ver se o char é UTF-8
// Link: http://stackoverflow.com/questions/1401317/remove-non-utf8-characters-from-string
$regex1 = <<<'END'
/
( [\x00-\x7F] # single-byte sequences 0xxxxxxx
| [\xC0-\xDF][\x80-\xBF] # double-byte sequences 110xxxxx 10xxxxxx
| [\xE0-\xEF][\x80-\xBF]{2} # triple-byte sequences 1110xxxx 10xxxxxx * 2
| [\xF0-\xF7][\x80-\xBF]{3} # quadruple-byte sequence 11110xxx 10xxxxxx * 3
)
| . # anything else
/x
END;
// resgato cada uma das tabelas, num loop
while ($row = mysql_fetch_row($res))
{
$table = $row[0];
// usando a função SHOW CREATE TABLE do mysql, exibo as funções de criação da tabela,
// exportando também isso, para nosso arquivo de backup
$res2 = mysql_query("SHOW CREATE TABLE $table");
// digo que o comando acima deve ser feito em cada uma das tabelas
while ($lin = mysql_fetch_row($res2)) {
// instruções que serão gravadas no arquivo de backup
fwrite($back, "\n#\n# Criação da Tabela : $table\n#\n\n");
fwrite($back, "$lin[1] ;\n\n#\n# Dados a serem incluídos na tabela\n#\n\n");
// seleciono todos os dados de cada tabela pega no while acima
// e depois gravo no arquivo .sql, usando comandos de insert
$res3 = mysql_query("SELECT * FROM $table");
$first = true;
while ($r = mysql_fetch_row($res3))
{
if ($first)
{
$sql = "INSERT INTO $table VALUES ";
$first = false;
}
else
{
$sql .= ',';
}
$sql .= "('";
$imploded = '';
$firstImplode = true;
foreach ($r as $reg)
{
if ($firstImplode)
{
$firstImplode = false;
}
else
{
$imploded .= "', '";
}
if ($checkUtf)
{
$escaped = str_replace('\'', "\\'", str_replace('\\', "\\\\", preg_replace($regex1, '$1', $reg)));
}
else
{
$escaped = str_replace('\'', "\\'", str_replace('\\', "\\\\", $reg));
}
$imploded .= $escaped;
}
$sql .= $imploded;
$sql .= "')\n";
}
if (!$first)
{
$sql .= ";\n";
fwrite($back, $sql);
}
}
}
// fechar o arquivo que foi gravado
fclose($back);
// gerando o arquivo para download, com o nome do banco e extensão sql.
$arquivo = $dbname . ".sql";
Header("Content-type: application/sql");
Header("Content-Disposition: attachment; filename=$arquivo");
// lê e exibe o conteúdo do arquivo gerado
readfile($arquivo);
?>