Weave 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

Easy Pdf Laravel Package

tarfin-labs/easy-pdf

Easy PDF makes PDF generation in Laravel effortless: render Blade views or raw HTML through headless Chrome, then save, download, or stream the result with a clean, fluent API. Configure page size, orientation, margins, and more in just a few lines.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Install the new major explicitly. composer require tarfin-labs/easy-pdf:^3.0. Do not let a bare composer update decide for you — 3.0.0 is a feat! (breaking) release, so Composer will refuse the jump silently on older apps until you widen your own constraints.

  • Check the platform matrix before anything else. v3.0.0 adds Laravel 13 and PHP 8.5 support and drops legacy versions. Read the require/require-dev block in the package's composer.json to confirm your exact floor (PHP minor and the lowest supported Laravel major) — the release note names the top of the matrix, not the bottom. If you are on Laravel 10/11 or PHP < 8.3, stay on ^2.11 and plan the framework upgrade as a separate project.

  • Publish config first. php artisan vendor:publish --tag=easy-pdf-config (verify the tag with php artisan vendor:publish — tag names occasionally change across majors). This gives you paper size, orientation, font paths, and temp/cache directories in one place instead of scattering options through call sites.

  • Smoke-test with one real document. A Blade invoice rendered to a streamed download is the canonical first use case:

    Route::get('/invoices/{invoice}/pdf', function (Invoice $invoice) {
        return EasyPdf::loadView('pdf.invoice', ['invoice' => $invoice])
            ->download("invoice-{$invoice->number}.pdf");
    });
    
  • Where to look first in the source: the facade/service-provider pair (to see what is bound and therefore swappable) and the config file (to see what the package actually forwards to the underlying PDF engine). Those two files answer most day-to-day questions faster than the README.

Implementation Patterns

  • Wrap the facade in your own builder. Rather than calling EasyPdf:: from controllers, introduce an InvoicePdf / ReportPdf class that takes a DTO and returns a response or a stored file. When 4.0 lands, or when you swap engines, you change one class instead of grepping 40 controllers.
  • Two output paths, one builder. Use ->download()/->stream() for interactive requests and a ->save($path)-style call (check the v3 signature) for queued/offline generation. Keeping both behind the same builder means the queued and synchronous outputs can't drift in layout.
  • Queue anything that embeds images or exceeds a few pages. PDF rendering is CPU- and memory-bound and blocks the PHP worker. Pattern: dispatch GenerateInvoicePdf job → write to the local/s3 disk → notify or expose a signed temporary URL. This also keeps request timeouts out of the equation on shared hosting.
  • Store views under a dedicated namespace (resources/views/pdf/…) and pass only plain arrays/DTOs into them. Anything you pass is serialized into the render context, so passing Eloquent models with lazy relations is how you get N+1s inside the renderer.
  • Centralize page setup in a Blade layout. Paper size, margins, header/footer, and font declarations belong in one pdf.layout template plus config; per-document overrides should be the exception and should be explicit at the call site.
  • Testing. Assert on the HTTP layer (Content-Type: application/pdf, Content-Disposition filename) rather than byte-comparing output — PDFs embed timestamps and generator IDs and will never be byte-stable. For storage flows, Storage::fake('local') + assertExists() is the cheapest reliable assertion. If you need content assertions, check the extracted text with a tool, not the raw stream.
  • Bind a fake in tests if the concrete renderer is bound in the container; that keeps your suite from shelling out to a heavyweight engine for every feature test.
  • Integration tip for API consumers: return the PDF as a base64 JSON field only for small documents; otherwise return a URL. Mobile clients and API gateways both handle large binary responses badly.

Gotchas and Tips

  • 3.0.0 is a hard cutoff, not a deprecation. There is no shim or compat layer — the legacy Laravel/PHP support is simply gone from the constraints. Audit composer.lock for other packages pinning the same framework majors before you start; the PDF wrapper is rarely the blocker, but it is often the package that surfaces the conflict.
  • PHP 8.5 is very new. The underlying PDF engine (and its font/imaging extensions) may lag behind the interpreter. If composer require fails with platform requirements, that error is coming from a transitive dependency, not from easy-pdf itself — check with composer why-not php 8.5.
  • Config cache bites on deploy. After publishing or editing the config, php artisan config:clear locally and ensure your deploy pipeline rebuilds the cache. Stale cached config is the single most common "my margins/paper size change did nothing" cause.
  • Fonts and non-Latin scripts. CJK, Arabic, and icon fonts need the font directory configured and the font cache warmed. In read-only container filesystems, point the temp/cache directory at a writable volume (e.g. /tmp or a mounted path) or rendering fails with an opaque engine error.
  • Memory and time limits. Large image-heavy documents routinely blow past 128M. Raise memory_limit/max_execution_time for the specific job or route, not globally. Downscale images before embedding — that is almost always cheaper than raising limits.
  • Remote images and allow_url_fopen. Many engines fetch images over HTTP themselves, bypassing Laravel's HTTP client, so timeouts, auth headers, and proxies behave differently than the rest of your app. Pre-download to a temp path or a storage disk and pass local paths.
  • Blade escaping inside HTML templates. User-supplied content rendered with {!! !!} is an injection vector and a malformed-PDF vector. Escape by default; sanitize any intentional raw HTML.
  • Debugging strategy: dump the HTML first (->loadView(...)->render()-style, or render the Blade view directly in the browser) and only then attempt PDF generation. Ninety percent of "broken PDF" reports are broken HTML/CSS, and PDF engines support a narrow CSS subset — no flexbox/grid in older engines, floats and tables only.
  • Extension points worth knowing: the container binding behind the facade (swap or decorate the renderer), the config file (engine options), and Blade itself (layouts, components, custom directives for page breaks). If a needed feature is missing, a custom Blade directive is usually a cleaner extension than forking the package.
  • Pin the major in composer.json ("^3.0") and add a note to your upgrade runbook: this package has shipped breaking majors before (2.x → 3.0), so treat the next one as scheduled maintenance rather than a surprise.
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.
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle