Скрипт для создания бэкапа файлов сайта и базы данных MODX Revolution

Этот скрипт создает архив файлов сайта и экспортирует базу данных в формате SQL. Скрипт размещается в корневой директории сайта и запускается через браузер. В результате его работы создаются два файла: архив с файлами сайта и файл с экспортированной базой данных, которые сохраняются в папке «backups» в корневом каталоге сайта.

Учтите, что данный скрипт создает архив только с 500 файлами из корневой директории сайта. Если у вас больше файлов, вам придется запустить скрипт несколько раз, меняя стартовую позицию для добавления файлов в архив и имя файла архива, чтобы создать несколько архивов с разными частями файлов.

<?php
/**
 * Скрипт для создания бэкапа файлов сайта и базы данных MODX Revolution
 *
 * Данный скрипт предназначен для создания архива файлов сайта на основе MODX
 * Revolution и экспорта базы данных в формате SQL. Скрипт должен быть размещен
 * в корневой директории сайта и запускается через браузер.
 *
 * Важно: перед использованием убедитесь, что пути к файлам конфигурации MODX
 * корректны и соответствуют вашей структуре папок.
 */

set_time_limit(0);

// Настройки
require_once 'config.core.php';
require_once MODX_CORE_PATH . 'config/' . MODX_CONFIG_KEY . '.inc.php';

$db_name = $database_dsn;
$db_user = $database_user;
$db_password = $database_password;
$db_host = $database_server;
$db_charset = $database_connection_charset;
$backup_folder = 'backups/';
$backup_files = $backup_folder . date('Y-m-d-H-i-s') . '-files.zip';
$backup_db = $backup_folder . date('Y-m-d-H-i-s') . '-db.sql';

// Извлекаем имя базы данных из строки DSN
preg_match('/dbname=([^;]*)/', $db_name, $matches);
$db_name = $matches[1];

// Создаем папку для бекапов, если ее нет
if (!file_exists($backup_folder) && !is_dir($backup_folder)) {
    mkdir($backup_folder);
}

/**
 * Функция для создания архива файлов сайта
 *
 * @param string $source      Путь к папке, которую нужно заархивировать
 * @param string $destination Путь для сохранения архива
 * @param int    $maxFiles    Максимальное количество файлов, добавляемых в архив
 *
 * @return bool Возвращает true, если архив успешно создан, иначе false
 */
function createZip($source, $destination, $maxFiles = 1000)
{
    $zip = new ZipArchive();
    if (!$zip->open($destination, ZipArchive::CREATE)) {
        return false;
    }

    $source = realpath($source);
    if (is_dir($source)) {
        $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source), RecursiveIteratorIterator::SELF_FIRST);
        $counter = 0;
        foreach ($files as $file) {
            if ($counter >= $maxFiles) {
                break;
            }
            $file = realpath($file);
            if (is_dir($file)) {
                $zip->addEmptyDir(str_replace($source . '/', '', $file . '/'));
            } elseif (is_file($file)) {
                $zip->addFromString(str_replace($source . '/', '', $file), file_get_contents($file));
                $counter++;
            }
        }
    } elseif (is_file($source)) {
        $zip->addFromString(basename($source), file_get_contents($source));
    }

    return $zip->close();
}

// Создаем архив файлов сайта
createZip('.', $ $backup_files, 500);

// Подключаемся к базе данных
$connection = new mysqli($db_host, $db_user, $db_password, $db_name);

// Проверяем подключение
if ($connection->connect_error) {
    die("Ошибка подключения к базе данных: " . $connection->connect_error);
}

// Устанавливаем кодировку соединения
$connection->set_charset($db_charset);

// Получаем список таблиц базы данных
$tables = [];
$result = $connection->query("SHOW TABLES");
while ($row = $result->fetch_row()) {
    $tables[] = $row[0];
}

// Экспортируем базу данных
$output = "";
foreach ($tables as $table) {
    $result = $connection->query("SELECT * FROM $table");
    $numColumns = $result->field_count;

    $output .= "DROP TABLE IF EXISTS $table;";
    $createTableResult = $connection->query("SHOW CREATE TABLE $table");
    $createTableRow = $createTableResult->fetch_assoc();
    $output .= "\n\n" . $createTableRow['Create Table'] . ";\n\n";

    for ($i = 0; $i < $numColumns; $i++) {
        while ($row = $result->fetch_row()) {
            $output .= "INSERT INTO $table VALUES(";
            for ($j = 0; $j < $numColumns; $j++) {
                $row[$j] = $connection->real_escape_string($row[$j]);
                $output .= isset($row[$j]) ? '"' . $row[$j] . '"' : '""';
                if ($j < ($numColumns - 1)) {
                    $output .= ',';
                }
            }
            $output .= ");\n";
        }
    }
    $output .= "\n\n\n";
}

// Сохраняем экспортированную базу данных
file_put_contents($backup_db, $output);

// Закрываем соединение с базой данных
$connection->close();

echo "Бекап успешно создан. Файлы сайта: $backup_files, база данных: $backup_db";

?>
Илья
28 апреля 2023, 15:23
modx.pro
1 081
+8

Комментарии: 10

Павел Романов
28 апреля 2023, 17:36
+2
Прошу прощения, но есть же BackupMODX ))
    Илья
    29 апреля 2023, 12:08
    0
    Данный скрипт был написан для сайта на котором BackupMODX, по ряду причин не устанавливался корректно и не выполнял свои функции.
Павел Бигель
29 апреля 2023, 22:47
0
Что это? Зачем это?

Удачи выполнить такой запрос на более менее большой бд
$result = $connection->query("SELECT * FROM $table");
    deleted
    30 апреля 2023, 21:51
    0
    дамп базы можно одной строкой через exeс сделать, правда не помню как
      Дима Касаткин
      01 мая 2023, 02:29
      0
      Дамп и сразу архивация, через php shell_exec вот так:
      mysqldump -ERv -u[user] -p[password] --databases [db_name] | gzip > dump_name.sql.gz
      Но @Илья все равно спасибо что поделился решением!
        Николай Савин
        01 мая 2023, 09:54
        +1
        exec на шаред хостингах обычно отключен.
        Правда это не отменяет того, что подобные операции через shell выполняют по SSH подключению
          Vladimir
          01 мая 2023, 11:55
          0
          Я использую для бэкапа бд этот скрипт github.com/ifsnop/mysqldump-php/blob/master/src/Ifsnop/Mysqldump/Mysqldump.php хорошо работает бэкапил бдшку с 50к товарами, и кучей страниц, конечно же через крон
        Александр Мельник
        30 апреля 2023, 09:25
        +6
        Человек решил свою проблему, поделился и молодец.
        Использовать нам или нет — это уже наше дело. Кто может — напишет лучше. Кто не может — возьмет этот пример. Зачем прям минусовать заметку.
          Prihod
          04 мая 2023, 14:54
          +1
          Ну хранить в корне сайта да ещё с такими названиями не очень то безопасно. Так как сайты постоянно на это сканируются для взлома. Знаю из практики так как на одном сайте стоит WAF и в логах все видно
            Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
            10