phplaravelpdfqueuejobs

How generate multiple PDF's in Laravel?


I'm having an issue where, despite passing correct data (which I've verified through logging and debugging), only one PDF is downloaded in the browser even though multiple PDFs for different products should be downloaded simultaneously. I have multiple PDF generation enabled in my browser settings.

Is it possible to handle this differently, or could there be errors in the template? One PDF is successfully downloaded with a status of 200 -> OK, but the second one is in status canceled without showing any other error. Both PDFs are generated in the storage, but only one is downloaded in the browser.

This is my job

<?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;
    }

    public function handle(): void
    {
        $idsToProcess = is_array($this->data['id']) ? $this->data['id'] : [$this->data['id']];
        Log::info('IDs to process: ' . json_encode($idsToProcess));
        // dd($idsToProcess);


        foreach ($idsToProcess as $productId) {
            /** Data by id from Item product */
            $this->data['store_item_product'] = StoreItemProduct::where('id', $productId)->first();
            $this->data['store_item'] = $this->data['store_item_product']->store_item()->first();
            $this->data['supplier'] = $this->data['store_item']->suppliers()->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_' . $productId;
                $pathInfo['filename'] = $filename;
                Log::info($filename);

                $this->data['path'] = $pathInfo['dirname'] . '/' . $filename . '.' . $pathInfo['extension'];

                /** Set template */
                $this->setOptionsAndTemplate();

                /** Create PDF with the unique filename */

            }
            CreatePDF::dispatchSync($this->data['path'], $this->data, $this->template, $this->options, 'hobs');
            Log::info('CreatePDF job dispatched for ID ' . $productId);

            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($this->data['path']);
        }
    }

    /**
     * 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()
    {
        $storeProductType = StoreItemProduct::where('id', $this->data['id'])->first()
            ->store_item()->first()
            ->store_item_type()->first();
        $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 blade

<body>

    <table cellspacing="2" width="100%">
        @if($content->store_item->store_item_type_id == 1)
        <tbody>
            <tr>
                <td>{{ $content->store_item->name }}</td>
            </tr>
            <tr>
                <td>
                    {{ $content->material->name }} <br>
                </td>
            </tr>
            <tr>
                <td><b>Breite:</b> {{ $content->materialproduct->webwidth }}</td>
            </tr>
        </tbody>
        @elseif($content->store_item->store_item_type_id == 2)
        <tbody>
            <tr>
                <td>{{ $content->store_item->name }}</td>
            </tr>
            <tr>
                <td>
                    {{ $content->material->name }} <br>
                </td>
            </tr>
            <tr>
                <td><b>Anzeigename:</b> {{ $content->materialproduct->display_name }}</td>
            </tr>
        </tbody>
        @elseif(in_array($content->store_item->store_item_type_id, [3, 4, 5, 6]))
    <tbody>
        <tr>
            <td>{{ $content->store_item->name }}</td>
        </tr>
    </tbody>
@endif
    </table>
</body>

And this is method in controller

public function viewAllProductInfo(Request $request)
    {
        $all_ids = $request->id;

        $storeItemProducts = StoreItemProduct::whereIn('id', $all_ids)->get();

        foreach ($storeItemProducts as $storeItemProduct) {
            event(new StoreViewItemProductLabelEvent($storeItemProduct, $request->all()));
        }
    }

I hope, that someone have experience with this problem and can help me to solve it.


Solution

  • I added sleep method into controller

      public function viewAllPdfEanCodes(Request $request)
        {
            $all_ids = $request->id;
            foreach ($all_ids as $id) {
                $store_product_unit = StoreProductUnit::findOrFail($id);
                event(new StoreViewPdfProductUnitEanCode($store_product_unit, $request->all()));
    
                sleep(3);
            }
        }
    

    So it has time for generating multiple PDF's in a row.