spatie / laravel-pdf

Create PDF files in Laravel apps
https://spatie.be/docs/laravel-pdf
MIT License
728 stars 56 forks source link

[Bug]: Defaults not used when running queue:work #107

Open Propaganistas opened 8 months ago

Propaganistas commented 8 months ago

What happened?

I've set defaults for the PdfBuilder in a service provider's boot() method as described in the docs.

When a PDF gets generated in a queued job:

How to reproduce the bug

  1. Create a fresh Laravel application (I'm on 10.x).
  2. Change queue connection to database and publish the jobs table
  3. Set defaults in AppServiceProvider boot() (e.g. Pdf::default()->margin(0.4, 0.4, 0.4, 0.4, Unit::Inch)
  4. Create a job that generates a PDF ( e.g. Pdf::view('welcome')->save('somewhere'))
  5. Run queue:work
  6. Enqueue the job using Tinker (or otherwise) and check result

Or temporarily add a dump statement in PdfBuilder's view() method to check the margins property and return early. You'll notice the margins are set when running queue:listen but remain null when running queue:work.

Package Version

1.4.0

PHP Version

8.3.3

Laravel Version

10.48.4

freekmurze commented 8 months ago

Is there some way to add a test for this?

Propaganistas commented 8 months ago

Is there some way to add a test for this?

Not sure. I think you could borrow ideas from framework tests?

https://github.com/laravel/framework/blob/10.x/tests/Queue/QueueWorkerTest.php

spatie-bot commented 4 months ago

Dear contributor,

because this issue seems to be inactive for quite some time now, I've automatically closed it. If you feel this issue deserves some attention from my human colleagues feel free to reopen it.

Propaganistas commented 4 months ago

Time to reopen as still unsolved.

zarulizham commented 3 months ago

Hi, I'm facing the same problem when generating the PDF under queue. If generate directly (sync), no issues. All defaults defined in app/Providers/AppServiceProvider.php boot().

meyer59 commented 1 month ago

Hi Same issue here

okaufmann commented 2 days ago

I just ran into the same problem. The issue shows the same behavior.

Here is some minimal test code:

use Spatie\LaravelPdf\Facades\Pdf;
use Spatie\Browsershot\Browsershot;

Pdf::default()->withBrowsershot(function (Browsershot $browserShot) {
            logger('prepare browsershot for pdf generation'); // only logs in sync context, never in a async job
});
okaufmann commented 2 days ago

It appears there is a resolution issue with the Facade or the Pdf::default() call, which returns a new instance of PdfFactory in queued jobs on each call. I am unsure of the exact cause.

As a workaround, I am registering the PdfBuilder manually and resolving it from the container when needed:

class PdfServiceProvider extends ServiceProvider
{
    #[Override]
    public function register(): void
    {
        $this->app->bind(PdfBuilder::class, function () {
            return (new PdfBuilder())->withBrowsershot(function (Browsershot $browsershot) {
                // Apply customizations to Browsershot
                return $browsershot;
            });
        });
    }
}

Then, I resolve the PdfBuilder like this:

$pdfBuilder = resolve(PdfBuilder::class); // Or inject it via constructor or method

$builder = $pdfBuilder->view($contextData->viewName, ['contextData' => $contextData])
            ->format(Format::A4)
            ->portrait()
            ->save($fileName);