PHP Website & Database Backup to ZIP

I recently had the need to do a full website backup (WordPress in this instance). I needed to zip up the main website files and MySQL database. After much trail and error, I have come up with a fairly simple solution.

WARNING: Never place zip files in a publicly accessible folder.


 * function to zip files and folders
 * @author	Drew Gauderman
 * @version	v1.0.0	Tuesday, March 24th, 2020.
 * @global
 * @param	string	$source
 * @param	string	$destination
 * @param	string	$prependPath
 * @return	void
function zipIt($source = './', $destination = './', $prependPath = '')
  // make sure the zip extension is enabled
  if (!extension_loaded('zip')) {
    throw new Exception('extension zip must be loaded!');

  // zip up folder/file check
  $source = realpath($source);
  if (!is_dir($source) &amp;&amp; !is_file($source)) {
    throw new Exception('source must be a valid path to a folder or file!');

  // start ZipArchive
  $zip = new ZipArchive();

  // create or overwrite the zip file
  if ($zip->open($destination, ZIPARCHIVE::CREATE || ZIPARCHIVE::OVERWRITE) === true) {
    // convert to realpath once file is created
    $destination = realpath($destination);

    // if folder, use recursive to grab all the contents
    if (is_dir($source)) {
      $iterator = new RecursiveDirectoryIterator($source);
      $files = new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::SELF_FIRST);

      // go through each file
      foreach ($files as $path) {
        echo "path: $path<br>";

        // file full path
        $path = realpath($path);

        // zip entire directory
        if (is_dir($path)) {
          $zip->addEmptyDir($prependPath . str_replace($source . DIRECTORY_SEPARATOR, '', $path . DIRECTORY_SEPARATOR));
        // zip file (but not the main zip file)
        elseif (is_file($path) &amp;&amp; $path !== $destination) {
          $zip->addFile($path, $prependPath . str_replace($source . DIRECTORY_SEPARATOR, '', $path));
    } else {
      // add file to the zip
      $zip->addFile($source, $prependPath . basename($source));

  // close ZipArchive

// file locations
$folderBackup = './folderToBackup';
$databaseBackup = './backup/database.sql';
$backupZip = './';

// mysql server details
$databaseServer = 'server_url';
$databaseUsername = 'database_username';
$databasePassword = 'database_password';
$databaseName = 'database_name';

// dump the database to .sql file. "(*) 2>&amp;1" helps to get any error messages.
$response = exec("(mysqldump --user=$databaseUsername --password='$databasePassword' --host=\"$databaseServer\" $databaseName --result-file=$databaseBackup) 2>&amp;1");
// echo "response: $response";

// zip up the website
zipIt($folderBackup, $backupZip);

echo "Done.";


The main “zipIt” function takes 3 arguments:

  • source: The folder to zip.
  • destination: where you want to zip to be saved.
  • prependPath: Allows you prepend a name, or specify a different folder path for files/folders.

Further Examples

// zip the WordPress config file to a ZIP file not in www root, and put it into a different folder within the zip
zipIt('./wp_config.php', '../', 'siteBackups/'); // file will be saved into the zip as "siteBackups/wp_config.php

View on GitHub at



E-mail : *

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.