I guess $file_name should be something like
$file_name = storage_path('app/certs/certs.zip');
Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.
I have a couple of nested queries that pull valid certs from the database by engineer.
I am trying to get a "Get all valid certs button' to create a zip containing all the valid certs (in date expiry > now() ) for a specific engineer. Certs are stored in /storage /app/certs and the database entries are 'qualification_id, filename, and url'.
I get the certs with a couple of nested loops but cant figure out how to create the zip.
Here is the controller.
public function get_all_valid_certs_by_engineer(Engineer $engineer)
{
$file_name = "certs.zip";
$zip = new ZipArchive;
$zip->open($file_name, ZipArchive::CREATE);
$qualifications = Qualification::where('engineer_id', $engineer->id)->get();
foreach($qualifications as $qualification)
{
$certs = $qualification->training_certs()->where('expiry', '>', now())->get();
if ($certs->count() > 0)
{
foreach ($certs as $cert)
{
$zip->addFile('storage/app/'.$cert->url);
}
}
}
$zip->close();
return response()->download($file_name);
}
This gives me the error
The file "certs.zip" does not exist
Any ideas?
This worked in the end. I was getting the zip paths and the file paths mixed up.
public function get_all_valid_certs_by_engineer(Engineer $engineer)
{
$zip_dir = storage_path().'/app/';
$public_dir = public_path();
$file_name = "certs.zip";
$zip = new ZipArchive;
$qualifications = Qualification::where('engineer_id', $engineer->id)->get();
if ($zip->open($public_dir.'/'.$file_name, ZipArchive::CREATE | ZipArchive::OVERWRITE) === TRUE)
{
foreach($qualifications as $qualification)
{
$certs = $qualification->training_certs()->where('expiry', '>', now())->get();
if ($certs->count() > 0)
{
foreach ($certs as $cert)
{
$zip->addFile($zip_dir.$cert->url, $cert->filename);
}
}
}
$zip->close();
}
return response()->download($public_dir.'/'.$file_name);
}
Please or to participate in this conversation.