Could someone please provide some useful advice on generating multiple PDF files at once? Or rather, how to generate them sequentially, meaning that one is downloaded first, and then the download for the next product is triggered? I need to create a solution where if multiple products are available, PDFs are generated for all of them with one click. However, I always encounter the issue that only one PDF is downloaded, typically the last one, while the previous requests end up being cancelled. I know that browsers don't allow multiple downloads at once, and I would normally try to use a zip file, but the client doesn't want that. Another idea I had was to combine all products into one PDF, but I have no idea how to do that. Page breaks don't seem to work for me, or rather, I'm not sure how to adjust the logic for that.
This is my job in laravel
<?php
namespace Modules\Store\Jobs\ItemProduct;
use App\Models\User;
use App\Jobs\Nodes\CreatePDF;
use Illuminate\Bus\Batchable;
use Illuminate\Bus\Queueable;
use App\Jobs\Nodes\UserNotice;
use Illuminate\Support\Facades\Bus;
use Illuminate\Support\Facades\Log;
use App\Libraries\WebDocumentsLibrary;
use Illuminate\Queue\InteractsWithQueue;
use Modules\Store\Models\StoreItemProduct;
use Modules\Store\Models\StoreProductUnit;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Modules\Store\Models\StoreItem;
class StoreViewItemProductLabelJob extends WebDocumentsLibrary implements ShouldQueue
{
use Batchable, Dispatchable, InteractsWithQueue, Queueable;
/** @var array */
private $data;
/** @var User */
private $user;
private $appID;
private $options;
private $template;
private $download;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct($data, $user, $appID, $download = true)
{
$this->data = $data;
$this->user = $user;
$this->appID = $appID;
$this->download = $download;
// Log::info('StoreViewItemProductLabelJob: Data received for ID ' . $this->data['id']);
// Log::info($data);
}
public function handle(): void
{
$products[] = $this->data;
foreach ($products as $product) {
/** Data by id from Item product */
$this->data['store_item_product'] = StoreItemProduct::where('id', $product['id'])->first();
$this->data['store_item'] = $this->data['store_item_product']->store_item()->first();
$this->data['supplier'] = $this->data['store_item']->supplier()->first();
$this->data['materialproduct'] = $this->data['store_item_product']->materialproduct()->first();
$this->data['material'] = $this->data['materialproduct'] ? $this->data['materialproduct']->material()->first() : null;
/** Date and time */
$this->data['date'] = date('d/m/Y');
$this->data['time'] = date('H:i:s');
if (!empty($this->data)) {
$pathInfo = pathinfo($this->data['path']);
$filename = $pathInfo['filename'] . '_product_' . $product['id'];
$pathInfo['filename'] = $filename;
$this->data['path'] = $pathInfo['dirname'] . '/' . $filename . '.' . $pathInfo['extension'];
/** Set template */
$this->setOptionsAndTemplate();
// Log::info('StoreViewItemProductLabelJob: Data prepared for PDF generation for ID ' . $product['id']);
/** Create PDF with the unique filename */
$create = CreatePDF::dispatch($this->data['path'], $this->data, $this->template, $this->options, 'hobs');
// Log::info('StoreViewItemProductLabelJob: CreatePDF job dispatched for ID ' . $product['id']);
Bus::chain([
new UserNotice(
$this->user,
"success",
__("purchases.document_was_generated", ["Object" => $filename]),
null,
["object" => "purchase", "download" => $this->download ? $this->data['path'] : null, "appID" => ($this->appID ?? null)]
)
])->dispatch();
// Log::info('StoreViewItemProductLabelJob: PDF generation successful for ID ' . $product['id']);
}
}
}
/**
* Handle a job failure.
*
* @param \Throwable $th
* @return void
*/
public function failed(\Throwable $th): void
{
UserNotice::dispatch($this->user, "error", __("general.error"), $th->getMessage());
}
/** set and get template for eancode PDF */
public function setOptionsAndTemplate()
{
$this->options = [
'format' => ['101', '151'],
'margin_left' => 5,
'margin_right' => 5,
'margin_top' => 5,
'margin_bottom' => 5,
'margin_header' => 0,
'margin_footer' => 0,
'orientation' => 'L',
];
$this->template = "store::documents/store/item_product";
return $this->template;
}
}
this is template for PDF
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Product Label</title>
<style>
body {
font-size: 34px;
}
</style>
</head>
<body>
@foreach($products as $product)
<table cellspacing="2" width="100%">
@if($product->store_item->store_item_type_id == 1)
<tbody>
<tr>
<td>{{ $product->store_item->name }}</td>
</tr>
<tr>
<td>{{ $product->material->name }} <br></td>
</tr>
<tr>
<td><b>Breite:</b> {{ $product->materialproduct->webwidth }}</td>
</tr>
</tbody>
@elseif($product->store_item->store_item_type_id == 2)
<tbody>
<tr>
<td>{{ $product->store_item->name }}</td>
</tr>
<tr>
<td>{{ $product->material->name }} <br></td>
</tr>
<tr>
<td><b>Anzeigename:</b> {{ $product->materialproduct->display_name }}</td>
</tr>
</tbody>
@elseif(in_array($product->store_item->store_item_type_id, [3, 4, 5, 6]))
<tbody>
<tr>
<td>{{ $product->store_item->name }}</td>
</tr>
</tbody>
@endif
</table>
<pagebreak></pagebreak>
@endforeach
</body>
</html>