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

Fpdi Laravel Package

setasign/fpdi

FPDI is a free PHP PDF document importer that reads pages from existing PDFs and uses them as templates in FPDF, TCPDF, or tFPDF. PSR-4 compatible, no special extensions required, with improved performance and lower memory use in v2.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps to Begin

  1. Installation: Add FPDI to your Laravel project via Composer, paired with your preferred PDF library (FPDF, TCPDF, or tFPDF). Example for FPDF:

    composer require setasign/fpdf:1.8.* setasign/fpdi:^2.5
    
  2. Basic Setup: Require the autoloader and initialize FPDI:

    require_once('vendor/autoload.php');
    use setasign\Fpdi\Fpdi;
    
    $pdf = new Fpdi();
    $pdf->AddPage();
    
  3. First Use Case: Import a PDF template and place it on a new page:

    $pdf->setSourceFile(storage_path('app/templates/invoice_template.pdf'));
    $tplId = $pdf->importPage(1); // Import first page
    $pdf->useTemplate($tplId, 10, 10, 100); // Place template at (10,10) with width 100mm
    $pdf->Output('invoice.pdf');
    

Where to Look First

  • Official Manual for API reference and workflows.
  • Example Directory in the GitHub repo for practical use cases (e.g., dynamic text overlay, multi-page imports).
  • Laravel Integration: Combine with Laravel’s storage system (e.g., storage_path()) for template management.

Implementation Patterns

Core Workflows

  1. Template Inheritance:

    • Pattern: Import a static PDF (e.g., a branded invoice) and overlay dynamic data.
    • Example:
      $pdf->setSourceFile($templatePath);
      $tplId = $pdf->importPage(1);
      $pdf->useTemplate($tplId, 10, 10, 200); // Full-page template
      $pdf->SetFont('Arial', 'B', 12);
      $pdf->SetXY(50, 50);
      $pdf->Cell(0, 10, "Dynamic Content: " . $order->amount);
      
  2. Multi-Page Documents:

    • Pattern: Import specific pages from a source PDF and assemble them into a new document.
    • Example:
      $pdf->setSourceFile($sourcePdf);
      $pageIds = [$pdf->importPage(1), $pdf->importPage(3)]; // Skip page 2
      foreach ($pageIds as $id) {
          $pdf->AddPage();
          $pdf->useTemplate($id, 0, 0, 0); // Full-page, no scaling
      }
      
  3. Dynamic Data Overlay:

    • Pattern: Use useTemplate() with offsets to position dynamic content (e.g., signatures, dates).
    • Example:
      $pdf->useTemplate($tplId, 10, 10, 150); // Template
      $pdf->SetXY(160, 10);
      $pdf->Cell(0, 10, "Signed: " . now()->format('Y-m-d'));
      

Integration Tips

  • Laravel Storage: Store templates in storage/app/public/templates/ and use Storage::disk('public')->path() to reference them.

    $pdf->setSourceFile(storage_path('app/public/templates/contract.pdf'));
    
  • Dynamic Template Selection: Use Laravel’s service container to resolve template paths based on context (e.g., user role).

    $templatePath = app('template.resolver')->resolve($user->role);
    
  • Error Handling: Wrap FPDI operations in try-catch blocks to handle malformed PDFs gracefully.

    try {
        $pdf->setSourceFile($path);
    } catch (\setasign\Fpdi\PdfParser\PdfParserException $e) {
        Log::error("Invalid PDF template: " . $e->getMessage());
        abort(500, "Template error");
    }
    
  • TCPDF/tFPDF: Replace Fpdi with setasign\Fpdi\Tcpdf\Fpdi or setasign\Fpdi\Tfpdf\Fpdi for advanced features (e.g., Unicode support, interactive forms).


Gotchas and Tips

Pitfalls

  1. Page Boundaries:

    • Issue: FPDI v2 drops support for /MediaBox paths starting with /. Use PdfReader\PageBoundaries constants instead.
    • Fix:
      $pdf->useTemplate($tplId, 10, 10, 100, '', '', true, PdfReader\PageBoundaries::MEDIABOX);
      
  2. Zero Width/Height:

    • Issue: Passing 0 for width/height in useTemplate() now throws InvalidArgumentException.
    • Fix: Use null or omit the parameter to auto-scale:
      $pdf->useTemplate($tplId, 10, 10, null, null); // Auto-scale
      
  3. Memory Exhaustion:

    • Issue: Complex PDFs (e.g., scanned documents) may trigger memory limits during parsing.
    • Fix:
      • Increase PHP’s memory_limit temporarily.
      • Use FpdiTrait::cleanUp() to release resources:
        $pdf->cleanUp();
        
  4. Unit Inconsistencies:

    • Issue: Templates with non-PT (point) units may render incorrectly.
    • Fix: Convert units explicitly or use PdfReader\PageBoundaries to enforce consistency.
  5. TCPDF Deprecation:

    • Issue: TcpdfFpdi is deprecated; use setasign\Fpdi\Tcpdf\Fpdi instead.

Debugging Tips

  • Visual Inspection: Use FPDI’s getTemplateSize() to debug template dimensions:

    $size = $pdf->getTemplateSize($tplId);
    Log::debug("Template size: " . $size['width'] . "x" . $size['height']);
    
  • Logging: Enable FPDI’s debug mode to log parsing issues:

    $pdf->setDebug(true);
    
  • Common Exceptions:

    • PdfParserException: Malformed PDF (e.g., corrupted file).
    • InvalidArgumentException: Invalid template ID or dimensions.
    • RuntimeException: Resource exhaustion or unsupported features.

Extension Points

  1. Custom Filters: Extend setasign\Fpdi\PdfParser\Filter\FilterInterface to support proprietary PDF filters (e.g., encryption).

  2. Annotation Handling: Override FpdiTrait::importAnnotations() to customize how links/bookmarks are imported.

  3. Laravel Service Provider: Bind FPDI to Laravel’s container for dependency injection:

    $this->app->bind('fpdi', function () {
        return new \setasign\Fpdi\Fpdi();
    });
    
  4. Dynamic Template Caching: Cache imported templates in Laravel’s cache system to avoid reprocessing:

    $cacheKey = 'fpdi_template_' . md5($templatePath);
    if (!Cache::has($cacheKey)) {
        $pdf->setSourceFile($templatePath);
        Cache::put($cacheKey, $pdf->importPage(1), now()->addHours(1));
    }
    

Performance Quirks

  • Stream Handling: FPDI supports reading from strings/stream resources, but large files may still cause timeouts. Use StreamReader::readBytes() with chunked reading for huge PDFs.

  • FlateDecode Fallback: The fallback decompression method (window size 31) may slow down rendering for compressed streams. Monitor performance with microtime():

    $start = microtime(true);
    $pdf->useTemplate($tplId, ...);
    Log::debug("Template rendering time: " . (microtime(true) - $start) . "s");
    
  • PHP 8+ Compatibility: FPDI v2.6+ drops support for PHP <7.2. Use declare(strict_types=1); in Laravel to enforce type safety.

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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport
twbs/bootstrap4