Backup do banco de dados MySQL com PHP

Hoje em dia temos diversas ferramentas para gerar backup de um banco de dados MySQL. Podemos gerar manualmente através do phpMyAdmin ou então por linha de comando utilizando o mysqldump, por exemplo.

Se o seu projeto estiver hospedado em uma hospedagem compartilhada, você provavelmente não tem acesso a linha de comando, e suas opções para automatizar o processo de backup ficam limitadas.

Neste artigo vou apresentar uma forma de fazer o backup com PHP, utilizando uma biblioteca que gera o backup completo do banco de dados sem precisar de nenhuma dependência. Além disso vamos implementar um método para apagar os backups antigos, mantendo apenas uma quantidade X de backups.

A Biblioteca

Primeiramente, vamos importar a biblioteca para nosso projeto utilizando o Composer (se você não estiver familiarizado com ele, dê uma olhada neste artigo). Para isso, vamos criar o composer.json.

{
  "require": {
    "ifsnop/mysqldump-php": "2.*"
  }
}

Agora basta rodar composer install no terminal para baixar a biblioteca na pasta vendor para que assim possamos utilizá-la.

A biblioteca possui os seguintes requerimentos:

  • PHP 5.3+
  • MySQL 4.1+

Criando classe para backup

Para o código ficar mais organizado vamos criar uma classe responsável pelo backup.

class BackupDatabase
{
    private $backupFolder;
    private $maxNumberFiles;

    private $host;
    private $database;
    private $username;
    private $password;

    /**
     * Construtor
     *
     * @param string $backupFolder Pasta onde serão armazenados os backups
     * @param int $maxNumberFiles Número máximo de backups que serão mantidos
     */
    public function __construct($backupFolder, $maxNumberFiles)
    {
        $this->backupFolder = $backupFolder;
        $this->maxNumberFiles = $maxNumberFiles;
    }

    /**
     * Define as informações de conexão com o banco de dados
     *
     * @param string $host
     * @param string $database
     * @param string $username
     * @param string $password
     */
    public function setDatabase($host, $database, $username, $password)
    {
        $this->host = $host;
        $this->database = $database;
        $this->username = $username;
        $this->password = $password;
    }

O construtor de nossa classe vai receber a pasta onde os backups serão armazenados e a quantidade de backups que serão mantidos. Criamos também o método setDatabase() para que possamos definir as informações de conexão com banco de dados, pois elas serão necessárias para biblioteca gerar o backup.

/**
 * Gera um backup
 *
 * @return void
 * @throws Exception
 */
public function generate()
{
    // Se as informações de conexão com o banco de dados não foram definidas
    if (empty($this->database) or empty($this->username) or empty($this->host)) {
        throw new \Exception('As informações de conexão com o banco de dados não foram definidas');
    }

    // Gerando nome único para o arquivo
    $fileName = date('YmdHis') . '.sql.gz';
    $filePath = $this->backupFolder . '/' . $fileName;

    // Definindo informações para geração do backup
    $dump = new Mysqldump("mysql:host={$this->host};dbname={$this->database}", $this->username, $this->password, array(
        'compress' => Mysqldump::GZIP,
    ));

    // Gerando backup
    $dump->start($filePath);
    echo "Gerado backup '{$filePath}'" . PHP_EOL;

    // Limpando backups antigos
    $this->clearOldFiles();
}

Basicamente geramos um nome único para o arquivo e então passamos os dados para a biblioteca gerar o backup. No quarto parâmetro podemos passar algumas configurações para a geração do backup. Neste exemplo, utilizamos apenas o compress para gerar o backup comprimido no formato GZIP. Por fim, chamamos o método clearOldFiles() para limpar os arquivos antigos.

/**
 * Limpa os arquivos de backups antigos
 *
 * @return void
 */
private function clearOldFiles()
{
    // Buscando itens na pasta
    $files = new \DirectoryIterator($this->backupFolder);

    // Passando pelos itens
    $sortedFiles = array();
    foreach ($files as $file) {
        // Se for um arquivo
        if ($file->isFile()) {
            // Adicionando em um vetor, sendo o índice a data de modificação
            // do arquivo, para assim ordenarmos posteriormente
            $sortedFiles[$file->getMTime()] = $file->getPathName();
        }
    }

    // Ordena o vetor em ordem decrescente
    arsort($sortedFiles);

    // Passando pelos arquivos
    $numberFiles = 0;
    foreach ($sortedFiles as $file) {
        $numberFiles++;
        // Se a quantidade de arquivo for maior que a quantidade
        // máxima definida
        if ($numberFiles > $this->maxNumberFiles) {
            // Removemos o arquivo da pasta
            unlink($file);
            echo "Apagado backup '{$file}'" . PHP_EOL;
        }
    }

}

Buscamos todos os arquivos na pasta definida e separamos eles em um vetor, onde o índice é data de modificação do arquivo. Através da função arsort() ordenamos o vetor pelo índice de forma decrescente, ou seja, os arquivos mais recentes vem primeiro. Por último, passamos pelo vetor e somente excluímos o arquivo, através da função unlink(), quando a posição no vetor for maior que a propriedade maxNumberFiles.

Utilizando a classe

<?php

// Incluindo o autoload do Composer para carregar a biblioteca
require_once 'vendor/autoload.php';

// Incluindo a classe que criamos
require_once 'class/BackupDatabase.php';

// Como a geração do backup pode ser demorada, retiramos
// o limite de execução do script
set_time_limit(0);

// Utilizando a classe para gerar um backup na pasta 'backups'
// e manter os últimos dez arquivos
$backup = new BackupDatabase('backups', 10);
$backup->setDatabase('localhost', 'database', 'root', '');
$backup->generate();

Incluímos o arquivo de autoload do Composer e nossa classe. Utilizamos a função set_time_limit() para retirar o tempo de limite de execução do script, pois dependendo do tamanho do banco de dados o processo pode demorar. Instanciamos um objeto de nossa classe, definindo que os backups serão gerados na pasta backups e serão mantidos os últimos dez arquivos. Por fim, geramos o backup através do método generate().

Para testar, você pode executar o arquivo que criamos através do terminal (você pode abrir pelo navegador também se preferir). Você deverá ver um retorno parecido com o abaixo.

$ php backup.php
Gerado backup 'backups/20170327023232.sql.gz'

Gerado o backup, é interessante também você tentar restaurá-lo para garantir que está tudo certo.

Automatizando o processo

Conseguimos fazer backup do banco de dados, porém para isso acontecer você deverá executar o arquivo backup.php toda vez manualmente. Tudo bem, você pode chamar esse trecho de código em alguma momento no seu projeto ou então criar um botão para que o próprio usuário faça o backup. Porém, o ideal neste caso seria automatizar o processo.

Se o seu projeto estiver em uma hospedagem compartilhada, verifique se no painel você não tem a opção de criar um CronjobUm Cronjob é nada mais que uma tarefa agendada para a execução de um comando. Sendo assim, você poderia agendar um comando (cURL normalmente) para chamar o backup.php uma vez por semana, por exemplo.

Caso seu projeto esteja hospedado em um servidor Linux em uma VPS (Virtual Private Server) e você tem acesso ao servidor via SSH (Secure Shell), você pode criar um Cronjob manualmente.

Enfim, não vou entrar em detalhes sobre como criar um Cronjob, pois existem diversos tutoriais excelentes na internet, porém acredito que está seja a melhor solução para automatizar o processo. Caso você tenha dificuldades em montar a sintaxe do Cronjob, este site é de grande ajuda.

Conclusão

O objetivo deste artigo foi mostrar uma forma de fazer backup de um banco de dados MySQL utilizando apenas PHP. Dessa forma você pode automatizar o processo,  caso não tenha outra opção em sua hospedagem.

Lembrando que estamos gerando um backup no próprio servidor, o ideal seria fazer uma cópia desses backups em outro lugar, em um servidor FTP ou serviço de armazenamento na nuvem, por exemplo.

Enfim, espero que de alguma forma este artigo tenha sido útil para você. Até a próxima.

Código fonte disponível em: https://github.com/rafaelcouto/backup-do-banco-de-dados-mysql-com-php/