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

Phantom Pdf Laravel Package

danielboendergaard/phantom-pdf

Laravel wrapper for generating PDFs with PhantomJS. Render HTML strings or URLs to PDF through a simple facade, with configurable paper size, orientation, margins, headers, footers, and other PhantomJS options. Useful for invoices, reports, and printable views.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install the package and publish its config:
    composer require danielboendergaard/phantom-pdf
    php artisan vendor:publish --provider="Danielboendergaard\PhantomPdf\PhantomPdfServiceProvider"
    
  2. Install the PhantomJS binary — this is the fragile step, not the composer part. Options: apt install phantomjs (older Debian/Ubuntu), brew install phantomjs, npm i -g phantomjs-prebuilt, or ship it inside your Docker image. Verify with phantomjs --version before touching Laravel.
  3. Open config/phantom-pdf.php first. Set the absolute path to the binary (and the bundled rasterize script if it isn't auto-detected) plus a writable temp_dir. Relative paths silently fail.
  4. First use case — render a Blade invoice and save it:
    use PDF;
    
    PDF::loadView('pdf.invoice', ['order' => $order])
        ->setPaper('a4', 'portrait')
        ->save(storage_path("app/invoices/{$order->id}.pdf"));
    
    Confirm the file exists before wiring up controllers — this validates binary path, temp dir, and view rendering in one shot.

Where to look when something breaks: config/phantom-pdf.php, then the package's main PhantomPdf class (to see which fluent methods actually exist), then the bundled rasterize.js (to see what CLI flags PhantomJS is being given).

Implementation Patterns

  • View vs. HTML. PDF::loadView() goes through Laravel's view engine, so Blade layouts, @include, and @foreach work. Use PDF::loadHTML($html) when the markup comes from an editor, a mail-preview endpoint, or a third-party template store. Avoid mixing both in the same class — pick one convention per controller/service.
  • Controller response vs. queued job. Streaming (->stream(), ->download()) is fine for small, user-triggered documents. Anything larger than a page or two, or anything batch generated, should be pushed to a queued job that calls ->save() to a disk path; PhantomJS is a synchronous subprocess and will block the request for seconds.
  • Wrap generation in a service. Don't sprinkle PDF::loadView(...) through controllers. A small InvoicePdfGenerator class that owns the view name, paper settings, and storage path makes swapping the backend later (Browsershot, Dompdf) a one-file change.
  • Headers/footers are typically set through the fluent API or a package option with raw HTML. Treat them as separate mini-templates and keep them free of Laravel's session/auth state — PhantomJS fetches nothing you don't hand it.
  • Asset inlining. Since PhantomJS has no Laravel session, link to absolute public URLs (asset() works only if the app is reachable from the server) or inline CSS/images as data URIs. Inlining is usually more reliable than relying on the local web server.
  • Artisan command is useful for one-off renders and smoke tests in CI: run it in a Docker health check to confirm the binary is installed and the config resolves.
  • Caching. If the same PDF is requested repeatedly, store the generated file (keyed by model + updated_at) and serve it back; regenerate only on change.

Gotchas and Tips

  • PhantomJS is abandoned (archived upstream in 2018, no security updates). It also has no working binary for Apple Silicon or many recent distros. If your team is starting fresh, evaluate Spatie Browsershot (headless Chrome) or Dompdf first; keep this package only if you already have PhantomJS running in a container.
  • Absolute binary path required. phantom, phantomjs on $PATH will work in your shell but not under php-fpm/queue workers whose PATH is minimal. Hard-code the absolute path in config and in Docker.
  • Permissions on temp_dir. The package writes intermediate files; www-data and www-data in a queue worker need write access to the same directory, or jobs fail with an unrelated-looking error.
  • Sandbox / OpenSSL issues. In containers, PhantomJS often needs --no-sandbox or --ssl-protocol=any passed through the package's option/method escape hatch. If you see empty PDFs or immediate non-zero exits, check the raw stderr first.
  • Async JS and web fonts may not be ready. PhantomJS snapshots the DOM when it renders. Client-side rendered content may appear blank; server-render everything you can, and use any delay/wait option the package exposes before increasing it blindly.
  • Missing fonts on Linux. CJK, emoji, and brand fonts may not be installed on the server even if they are on your Mac. Install fonts in the Docker image, not just the composer project.
  • Config caching. php artisan config:cache combined with env() values inside the config file is the classic Laravel trap — the binary path gets baked in. Use env only in deployment, and re-cache after changing it.
  • Octane / long-running workers. Each call spawns a PhantomJS child process. Under Octane or a long-running queue worker, watch for zombie processes and memory growth; consider running PDF jobs on a dedicated queue with a max job count.
  • Return values differ. save() returns a boolean; stream()/download() return a Laravel response. Don't try to ->save() a response and don't ->stream() inside a queued job.
  • Debugging. Reproduce the failure outside Laravel by running the same phantomjs rasterize.js ... command the package builds. If that succeeds, the problem is config/permissions; if it fails, it's the binary/environment — this split saves a lot of time.
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.
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels