Skip to content

Tout pour WordPress, le développement web — et plus encore

💾 Sauvegarder et restaurer une base de données MySQL via PHP

💾 Sauvegarder et restaurer une base de données MySQL via PHP

Perdre une base de données, c’est perdre des commandes, des utilisateurs et du contenu en quelques secondes. Pour un propriétaire de site WordPress, la sauvegarde n’est pas un «plus», c’est une obligation. Mais se connecter manuellement à phpMyAdmin chaque jour fait perdre du temps et, le jour où vous en avez besoin, la sauvegarde n’est tout simplement pas là.

Un script PHP résout le problème: vous lui donnez l’accès à la base de données, il exporte la structure et les données dans un fichier SQL. En cinq minutes de configuration, vous obtenez une sauvegarde reproductible et programmable que vous n’oublierez pas de lancer.

À suivre: des scripts prêts à l’emploi pour la sauvegarde et la restauration MySQL en PHP. Nous allons détailler leur fonctionnement, où trouver les identifiants et comment planifier une sauvegarde automatique pour que votre base de données ne reste jamais sans protection.

💡 Aperçu rapide:

  • Connexion à MySQL via mysqli, récupération de la liste des tables et export de la structure
  • Constitution du dump SQL: CREATE TABLE suivi des INSERT pour chaque table, sauvegarde dans un fichier
  • Restauration: lecture du dump et exécution des requêtes en une seule fois via mysqli_multi_query
  • Automatisation via Cron (Linux) ou le Planificateur de tâches (Windows) qui exécute le script sans votre intervention
  • Compression en .gz et rotation des anciennes copies pour économiser de l’espace et conserver un historique

Étape 1: Identifiants et environnement, ce dont vous avez besoin avant de lancer le script

Avant d’écrire le code, rassemblez trois éléments: les identifiants MySQL, un répertoire pour stocker les sauvegardes et une idée précise de l’endroit où le script va s’exécuter.

Pour vous connecter à la base de données, vous avez besoin de l’hôte (généralement localhost ou 127.0.0.1), du nom d’utilisateur, du mot de passe et du nom de la base. Sur un site WordPress, ces informations se trouvent dans wp-config.php: les constantes DB_HOST (serveur), DB_USER (identifiant), DB_PASSWORD (mot de passe) et DB_NAME (nom de la base).

Créez le répertoire de sauvegarde en dehors du dossier public du site. Placez le dossier backups/ un niveau au-dessus de public_html, afin que les fichiers SQL ne soient pas accessibles depuis le navigateur. Les droits en écriture (chmod 755 ou chmod 775) sont obligatoires: sans eux, fopen() et fwrite() échoueront avec une erreur.

Le script PHP s’exécute en ligne de commande: php backup.php. L’exécution via le web (par navigateur) est également possible, mais la ligne de commande est plus sûre: personne ne devinera l’URL du script et ne pourra vider votre base de données.

Étape 2: Script PHP pour la sauvegarde de la base de données

Le script procède en trois passes: il récupère la liste des tables, pour chacune il exporte la structure (SHOW CREATE TABLE), puis les données (SELECT *). Le résultat est assemblé en une seule chaîne et écrit dans un fichier .sql. Sauvegardez le code sous le nom backup.php et exécutez-le depuis le terminal.

1<?php
2
3$connection = mysqli_connect('localhost', 'user', 'pass', 'my_database');
4
5if (!$connection) {
6 die('Ошибка подключения: ' . mysqli_connect_error());
7}
8
9$tables = [];
10$result = mysqli_query($connection, "SHOW TABLES");
11while ($row = mysqli_fetch_row($result)) {
12 $tables[] = $row[0];
13}
14
15$dump = '';
16foreach ($tables as $table) {
17 $dump .= 'DROP TABLE IF EXISTS ' . $table . ";\n";
18
19 $create = mysqli_query($connection, "SHOW CREATE TABLE " . $table);
20 $row = mysqli_fetch_row($create);
21 $dump .= $row[1] . ";\n\n";
22
23 $data = mysqli_query($connection, "SELECT * FROM " . $table);
24 $num_fields = mysqli_num_fields($data);
25
26 while ($row = mysqli_fetch_row($data)) {
27 $dump .= "INSERT INTO " . $table . " VALUES(";
28 for ($j = 0; $j < $num_fields; $j++) {
29 if (isset($row[$j])) {
30 $row[$j] = mysqli_real_escape_string($connection, $row[$j]);
31 $dump .= '"' . $row[$j] . '"';
32 } else {
33 $dump .= 'NULL';
34 }
35 if ($j < $num_fields - 1) {
36 $dump .= ',';
37 }
38 }
39 $dump .= ");\n";
40 }
41 $dump .= "\n\n";
42}
43
44$filename = 'backups/dump_' . date('Y-m-d_H-i-s') . '.sql';
45$handle = fopen($filename, 'w+');
46fwrite($handle, $dump);
47fclose($handle);
48
49echo "Бэкап сохранён: " . $filename . "\n";
50
51?>

Voici ce qui se passe ligne par ligne. mysqli_connect() ouvre une connexion; si l’accès est refusé, le script s’arrête avec un message clair plutôt que de continuer silencieusement. La boucle SHOW TABLES rassemble les noms des tables dans un tableau.

Pour chaque table, SHOW CREATE TABLE renvoie exactement une ligne dont le deuxième champ est la requête DDL complète. Nous ajoutons DROP TABLE IF EXISTS avant, afin que le dump puisse être appliqué sur une base propre sans conflit.

SELECT * lit toutes les lignes. La fonction mysqli_real_escape_string() échappe les guillemets et les caractères spéciaux à l’intérieur des valeurs; contrairement à addslashes(), elle respecte l’encodage de la connexion et ne laisse pas passer d’injections via des séquences multioctets. Les valeurs NULL sont insérées comme NULL, et non comme une chaîne vide.

Le nom du fichier contient la date et l’heure d’exécution, ce qui est pratique pour la rotation. Le fichier s’ouvre en mode w+ (création ou écrasement) et reçoit l’intégralité du dump en une seule opération fwrite().

Étape 3: Script de restauration de la base de données à partir d’un dump SQL

Le script inverse lit le fichier .sql et exécute les requêtes sur la base de données. En pratique, les dumps pèsent souvent plusieurs dizaines de mégaoctets, donc file_get_contents() suivi d’un explode sur ; n’est pas la meilleure option pour la production. Mais pour l’apprentissage et les petites bases, l’approche fonctionne.

Sauvegardez-le sous le nom restore.php. Avant de l’exécuter, faites une sauvegarde complète de la base actuelle: la restauration écrase les tables.

1<?php
2
3$connection = mysqli_connect('localhost', 'root', '', 'test');
4
5if (!$connection) {
6 die('Ошибка подключения: ' . mysqli_connect_error());
7}
8
9$filename = 'backups/dump_2026-06-14_12-00-00.sql';
10
11if (!file_exists($filename)) {
12 die('Файл дампа не найден: ' . $filename);
13}
14
15$contents = file_get_contents($filename);
16
17if (mysqli_multi_query($connection, $contents)) {
18 do {
19 if ($result = mysqli_store_result($connection)) {
20 mysqli_free_result($result);
21 }
22 } while (mysqli_next_result($connection));
23 echo "База восстановлена из: " . $filename . "\n";
24} else {
25 echo "Ошибка восстановления: " . mysqli_error($connection) . "\n";
26}
27
28mysqli_close($connection);
29
30?>

La différence clé par rapport à un mysqli_query() ligne par ligne est mysqli_multi_query(). Cette fonction accepte une chaîne contenant plusieurs requêtes SQL et les exécute séquentiellement en un seul appel. La boucle do...while avec mysqli_next_result() est obligatoire: sans elle, les requêtes suivantes ne s’exécuteront pas et la connexion restera bloquée.

mysqli_store_result() récupère le résultat de la requête en cours, et mysqli_free_result() libère la mémoire. Si la requête est un INSERT ou un CREATE TABLE, le résultat sera false, ce qui est normal: le script passe simplement à la suivante.

Remarque: le script n’exécute pas de DROP DATABASE et ne recrée pas la base elle-même. Il s’attend à ce que la base test existe déjà. Par sécurité, la première ligne du dump peut contenir CREATE DATABASE IF NOT EXISTS.

Étape 4: Automatisation de la sauvegarde via Cron et compression

L’exécution manuelle convient pour des tâches ponctuelles. Mais sur un site en production, la sauvegarde doit se faire sans vous, chaque nuit pendant que vous dormez.

Sur un serveur Linux, ajoutez une tâche dans Cron: crontab -e et la ligne 0 3 * * * php /path/to/backup.php exécute le script tous les jours à 3 h du matin. Sous Windows, utilisez le Planificateur de tâches avec l’action «démarrer un programme» php.exe et le chemin du script en argument.

Deux améliorations qui transforment un script d’apprentissage en outil prêt pour la production:

Compression. Après l’écriture du fichier .sql, ajoutez exec("gzip " . $filename);: la taille du dump sera réduite de 5 à 10 fois. Pour la restauration, gunzip décompresse le fichier.

Rotation. Conservez les sauvegardes des 7 derniers jours, supprimez le reste. Option simple: ajoutez un nettoyage des fichiers de plus de N jours au début du script:

1$retention_days = 7;
2$backup_dir = 'backups/';
3foreach (glob($backup_dir . '*.sql.gz') as $file) {
4 if (filemtime($file) < time() - $retention_days * 86400) {
5 unlink($file);
6 }
7}

Vous obtenez ainsi un système autonome: le script s’exécute selon le planning, crée une sauvegarde compressée avec la date dans le nom du fichier et nettoie les anciennes versions. Avec un peu de rigueur et 20 minutes de configuration, vous remplacez un plugin payant.

La vidéo ci-dessus montre le cycle complet de sauvegarde automatique: du fichier de configuration à la vérification du .sql.gz compressé dans le dossier backups/. L’approche est exactement la même que celle décrite dans cet article, avec des contrôles d’erreur et une journalisation supplémentaires.

⁉️🤔 FAQ

Est-il sûr de stocker le mot de passe MySQL dans un script PHP?

Stocker des identifiants en clair dans un script n’est acceptable que si le fichier se trouve en dehors du répertoire public du site et est inaccessible depuis le navigateur. Il est préférable de déplacer les identifiants dans un fichier config.php séparé, en dehors de public_html, et de l’inclure via require. Encore plus fiable: passez le mot de passe par une variable d’environnement: getenv('DB_PASS').

Puis-je sauvegarder uniquement certaines tables?

Oui. Remplacez SHOW TABLES par un tableau explicite de noms: $tables = ['wp_posts', 'wp_postmeta', 'wp_options'];. Ou excluez les tables sans importance via if (!in_array($table, ['wp_litespeed_cache', 'wp_actionscheduler_logs'])). En pratique, les tables de cache et de logs occupent une part significative de la taille de la base et ne sont pas nécessaires pour une restauration.

Quel espace occupe une sauvegarde de base de données d’un site WordPress moyen?

Un dump SQL non compressé d’une base contenant 500 articles et 15 plugins pèse entre 15 et 40 Mo. Après gzip, entre 2 et 8 Mo. Sur un mois de sauvegardes quotidiennes avec compression, cela représente 100 à 300 Mo, ce qui est négligeable pour un serveur disposant de 20 Go de disque. Une rotation sur 7 jours maintient l’espace occupé entre 50 et 100 Mo.

Que faire si le fichier de sauvegarde est corrompu?

Avant de restaurer, vérifiez l’intégrité: gunzip -t dump.sql.gz pour un fichier compressé, head -n 20 dump.sql pour un fichier non compressé, et assurez-vous que le fichier commence par des commentaires SQL, et non par des données binaires illisibles. Ne restaurez jamais un dump corrompu, vous perdriez des données. C’est précisément pour cela que vous conservez au moins les 2 ou 3 dernières copies.

En quoi cette approche diffère-t-elle des plugins de sauvegarde WordPress?

Un plugin comme UpdraftPlus offre une interface web, des sauvegardes incrémentales et l’envoi vers le cloud «clé en main». Un script PHP, c’est le contrôle total du processus sans code supplémentaire dans l’administration. Pour un développeur qui travaille déjà avec le serveur, le script est plus rapide et plus transparent. Pour un client sans accès console, un plugin est plus pratique.

Script manuel, mysqldump ou plugin: que choisir selon votre besoin

Un script de sauvegarde PHP apporte l’essentiel: la compréhension de ce qui arrive exactement à votre base de données pendant la sauvegarde. Vous ne faites pas confiance à une boîte noire, vous contrôlez chaque requête.

Si le site est en production et que la rapidité compte, utilisez mysqldump. Une seule commande mysqldump -u user -p db_name | gzip > dump.sql.gz fait la même chose, mais bien plus rapidement, car elle travaille au niveau du moteur MySQL, et non par un SELECT ligne par ligne. Le script PHP est destiné à l’apprentissage, aux scénarios personnalisés (sauvegarder non pas toute la base, mais le résultat d’une requête spécifique) et aux environnements où mysqldump n’est pas disponible.

Si le site est sous WordPress et que vous ne voulez pas plonger dans la console, n’importe quel plugin de sauvegarde répondra au besoin sans code. UpdraftPlus, BackWPup, Duplicator capturent à la fois la base de données et les fichiers du site.

Commencez par un script manuel, comprenez comment un dump SQL est constitué. Ensuite, mettez en place Cron et la compression. Dernière étape: vérifiez la restauration sur un serveur de test. Une sauvegarde sans vérification de la restauration n’est pas considérée comme faite. Quel outil utilisez-vous pour la sauvegarde de votre base de données? Dites-le en commentaire.