So I needed to archive data from multiple models into a single zip file. My first attempt was to use the Chumper/Zipper package for Laravel, this however did not work for me as I encountered several problems with it. The results were inconsistent. Maybe I was using it incorrectly or there was something I missed somehow. After several hours of fighting with it, I decided to go the native PHP way.

Here’s an example of how I got it to work. This code is part of a function in the appropriate controller:

<?php
// Convert data to JSON
$data   = User::where('account_id', $account_id)->get()->toJson();
$json[] = $this->saveJsonFile($account_id . '_users.json', $data);

$data   = Account::where('id', $account_id)->get()->toJson();
$json[] = $this->saveJsonFile($account_id . '_accounts.json', $data);

// Set the storage path and the zip file name
$storage    = storage_path() . '/archive/';
$zip_file   = $account_id . '_archive_' . time() . '.zip';

// Open a new zip archive for creation
$zip    = new ZipArchive;
$open   = $zip->open($storage . $zip_file, ZipArchive::CREATE);

// Add each JSON file to the zip archive
if ($open === true) {
    foreach ($json as $file) {
        $zip->addFile($file);
    }
    $zip->close();
} else {
    throw Exception;
}

// Clean up
File::delete($json);
?>

The code above calls this private function, which exists in the same controller:

<?php
private function saveJsonFile($file_name, $contents)
{
    $file = storage_path() . '/archive/' . $file_name;
    
    // Save file
    if ( ! File::put($file, $contents)) {
        throw Exception;
    }

    return $file;
}
?>

And that's all there is to it.