Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Chrome Pdf Bundle Laravel Package

daif/chrome-pdf-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require daif/chrome-pdf-bundle
    

    Add to config/bundles.php:

    return [
        // ...
        Daif\ChromePdfBundle\ChromePdfBundle::class => ['all' => true],
    ];
    
  2. Basic Configuration Edit config/packages/chrome_pdf.yaml:

    chrome_pdf:
        chrome_binary: '/usr/bin/chromium'  # or '/usr/bin/google-chrome'
        options:
            headless: true
            args: ['--no-sandbox', '--disable-gpu']
    
  3. First Use Case: Generate PDF from URL

    use Daif\ChromePdfBundle\Service\PdfGenerator;
    
    class SomeController extends AbstractController
    {
        public function generatePdf(PdfGenerator $pdfGenerator): Response
        {
            $pdf = $pdfGenerator->fromUrl('https://example.com')
                ->saveAs('/path/to/output.pdf');
    
            return $this->file($pdf->getPath());
        }
    }
    
  4. First Use Case: Generate PDF from HTML

    $pdf = $pdfGenerator->fromHtml('<h1>Hello World</h1>')
        ->saveAs('/path/to/output.pdf');
    

Implementation Patterns

Builder-Based API Workflow

The bundle follows a fluent builder pattern for PDF generation. Typical workflow:

$pdf = $pdfGenerator
    ->fromUrl('https://example.com')
    ->setOptions(['format' => 'A4', 'margin' => '1cm'])
    ->setHeaders(['User-Agent' => 'MyApp/1.0'])
    ->setTimeout(30)
    ->saveAs('/tmp/output.pdf');

Common Use Cases

  1. Dynamic PDF Generation in Controllers

    public function generateInvoice(PdfGenerator $pdfGenerator, $invoiceId): Response
    {
        $html = $this->twig->render('invoice/pdf.html.twig', ['id' => $invoiceId]);
        $pdf = $pdfGenerator->fromHtml($html)
            ->setOptions(['format' => 'A4', 'margin' => '0.5cm'])
            ->saveAs('/tmp/invoices/'.$invoiceId.'.pdf');
    
        return $this->file($pdf->getPath());
    }
    
  2. Background PDF Generation with Symfony Messenger

    use Daif\ChromePdfBundle\Message\GeneratePdfMessage;
    
    $bus->dispatch(new GeneratePdfMessage(
        url: 'https://example.com',
        outputPath: '/tmp/output.pdf',
        options: ['format' => 'A4']
    ));
    
  3. Integration with Symfony UX Turbo

    // In your Stimulus controller
    connect() {
        this.pdfButton.addEventListener('click', () => {
            fetch('/generate-pdf', {
                headers: { 'Accept': 'application/pdf' }
            })
            .then(response => response.blob())
            .then(blob => {
                const url = window.URL.createObjectURL(blob);
                const a = document.createElement('a');
                a.href = url;
                a.download = 'document.pdf';
                a.click();
            });
        });
    }
    
  4. Custom Chrome Binary per Environment Use environment variables in chrome_pdf.yaml:

    chrome_pdf:
        chrome_binary: '%env(CHROME_BINARY)%'
    

    Set in .env:

    CHROME_BINARY=/usr/local/bin/google-chrome
    
  5. Reusing Chrome Instances For performance, reuse Chrome instances with a pool:

    # config/packages/chrome_pdf.yaml
    chrome_pdf:
        pool:
            enabled: true
            max_instances: 5
    

Gotchas and Tips

Pitfalls and Debugging

  1. Chrome Binary Not Found

    • Symptom: ChromeBinaryNotFoundException
    • Fix: Verify chrome_binary path in config. Test with:
      which chromium-browser google-chrome
      
    • Tip: Use absolute paths (e.g., /usr/bin/google-chrome-stable).
  2. Headless Chrome Fails on Linux

    • Symptom: Chrome crashes silently or renders blank PDFs.
    • Fix: Add required args:
      chrome_pdf:
          options:
              args: ['--no-sandbox', '--disable-gpu', '--single-process']
      
    • For SELinux systems, add:
      args: ['--no-sandbox', '--disable-gpu', '--disable-dev-shm-usage']
      
  3. Memory Leaks with Reused Instances

    • Symptom: Chrome processes accumulate, causing OOM errors.
    • Fix: Enable the pool and set max_instances:
      chrome_pdf:
          pool:
              enabled: true
              max_instances: 3
              ttl: 300 # 5 minutes
      
  4. Slow PDF Generation

    • Cause: Default timeout (30s) may be too low for complex pages.
    • Fix: Increase timeout:
      $pdfGenerator->fromUrl('https://slow-site.com')
          ->setTimeout(60); // 60 seconds
      
  5. PDFs with Missing Content

    • Cause: Chrome may not wait for dynamic content (e.g., AJAX, lazy-loaded images).
    • Fix: Use waitForSelector:
      $pdfGenerator->fromUrl('https://example.com')
          ->waitForSelector('#dynamic-content')
          ->saveAs('/tmp/output.pdf');
      
  6. Font Rendering Issues

    • Symptom: PDFs show placeholder boxes for fonts.
    • Fix: Ensure Chrome has access to system fonts or bundle custom fonts:
      chrome_pdf:
          options:
              args: ['--disable-font-subpixel-positioning']
      

Configuration Quirks

  1. Environment-Specific Configs Override configs per environment using config/packages/chrome_pdf_{env}.yaml:

    # config/packages/chrome_pdf_prod.yaml
    chrome_pdf:
        options:
            args: ['--no-sandbox', '--disable-setuid-sandbox']
    
  2. Custom Chrome Flags Pass additional flags via args:

    chrome_pdf:
        options:
            args: [
                '--disable-extensions',
                '--disable-notifications',
                '--disable-default-apps',
                '--disable-infobars'
            ]
    
  3. Proxy Support Configure proxy for restricted environments:

    chrome_pdf:
        options:
            args: [
                '--proxy-server=http://proxy.example.com:8080',
                '--proxy-bypass-list=*.internal'
            ]
    

Extension Points

  1. Custom PDF Generator Extend the base generator:

    use Daif\ChromePdfBundle\Service\PdfGeneratorInterface;
    
    class CustomPdfGenerator implements PdfGeneratorInterface
    {
        public function fromUrl(string $url): self
        {
            // Custom logic (e.g., add auth headers)
            return $this;
        }
    
        // Implement other methods...
    }
    

    Register as a service:

    services:
        Daif\ChromePdfBundle\Service\PdfGenerator:
            alias: 'App\Service\CustomPdfGenerator'
    
  2. Event Listeners for PDF Generation Listen to chrome_pdf.generate events:

    use Daif\ChromePdfBundle\Event\PdfGenerateEvent;
    use Symfony\Component\EventDispatcher\EventSubscriberInterface;
    
    class PdfLogger implements EventSubscriberInterface
    {
        public static function getSubscribedEvents()
        {
            return [
                PdfGenerateEvent::NAME => 'onPdfGenerate',
            ];
        }
    
        public function onPdfGenerate(PdfGenerateEvent $event)
        {
            // Log or modify the PDF generation process
        }
    }
    
  3. Custom Chrome Binary Wrapper For unsupported Chrome versions, create a wrapper script (e.g., /usr/local/bin/chrome-wrapper):

    #!/bin/bash
    exec /usr/bin/google-chrome-stable --headless --disable-gpu "$@"
    

    Then point chrome_binary to this wrapper.

  4. Integration with Symfony Workflow Use the bundle in a Symfony workflow for multi-step PDF generation:

    # config/packages/workflow.yaml
    app.generate_pdf_workflow:
        support:
            triggered_by: 'app.generate_pdf'
        places:
            - reading_url
            - generating_pdf
            - saving_file
        transitions:
            read_url:
                from: reading_url
                to: generating_pdf
            generate_pdf:
                from: generating_pdf
                to: saving_file
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
comsave/common
alecsammon/php-raml-parser
chrome-php/wrench
lendable/composer-license-checker
typhoon/reflection
mesilov/moneyphp-percentage
mike42/gfx-php
bookdown/themes
aura/view
aura/html
aura/cli
povils/phpmnd
nayjest/manipulator
omnipay/tests
psr-mock/http-message-implementation
psr-mock/http-factory-implementation
psr-mock/http-client-implementation
voku/email-check
voku/urlify
rtheunissen/guzzle-log-middleware