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

Php Phantomjs Laravel Package

jonnyw/php-phantomjs

PHP PhantomJS is a headless browser wrapper for PHP that lets you load pages, run JavaScript, capture screenshots, and export to PDF. It provides a clean, extensible API over the PhantomJS binary, supports custom scripts, and works with any PHP project.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit jonnyw/php-phantomjs is a thin PHP wrapper that shells out to a native PhantomJS binary using symfony/process, assembling the CLI invocation from Twig-templated "procedures." It ships a Laravel service provider and facade (PhantomJs), so it drops into a Laravel service container cleanly. Architecturally it is a renderer adapter, not a component of application domain logic — it produces a response payload (HTML, PDF, screenshot) and has no business rules. That makes it replaceable behind an interface, which is the only reason it is tolerable at all. The design assumes a host-installed binary whose path, version, and ABI are managed outside Composer; that assumption is the core weakness in any containerized or platform-managed deployment.

Integration feasibility Feasible in a legacy context and hostile in a modern one. The package's last release (2018-04-03) pins Symfony process/config/filesystem at 2.x–4.x eras, so on Laravel 9+ (Symfony 6) Composer resolution is likely to fail or force downgrades of shared transitive dependencies — this needs a composer why-not check before anything else. On Laravel 5.5–8 with PHP 7.x it will install. The real blocker is not PHP: it is obtaining a working PhantomJS 2.1.1 binary. That binary is not built for Apple Silicon, is unreliable on modern glibc/libssl 1.1+, and has no supported distribution. Integration effort is small; sustaining the integration is the cost.

Technical risk Critical. Every risk vector is unowned:

  • PhantomJS itself was archived in 2018 and is EOL; unpatched QtWebKit carries known memory-safety CVEs.
  • The PHP package is archived — no fixes for PHP 8, Symfony 6, or Laravel 10/11.
  • Rendering untrusted URLs opens SSRF and file:// local-read exposure with no meaningful sandbox.
  • Build reproducibility is poor: no reliable source of a pinned, verified binary image.
  • The 1,424 stars / 0 dependents pairing is internally contradictory and signals a stale metric; either way it indicates no active consuming ecosystem to lean on for fixes.

Key questions

  1. Is the actual requirement "HTML→PDF," "screenshot," or "execute JS and return the DOM"? Only the third genuinely needs a headless browser, and even then not this one.
  2. Which Laravel/PHP version is in play, and does Composer resolve without downgrading Symfony?
  3. What deployment substrate? If the target is Alpine, ARM, or a distroless image, PhantomJS is effectively unavailable.
  4. Is there an existing renderer abstraction, or are Client calls scattered across controllers and jobs?
  5. What is the compliance posture for running an unpatched browser engine against untrusted input?

Integration Approach

Stack fit Best fit: a Laravel 5.5–8 / PHP 7.x application that already has PhantomJS provisioned (or can be pinned to a legacy Debian base image) and needs PDF or screenshot generation in a background job. Poor fit: greenfield Laravel 10+, PHP 8.2+, ARM CI runners, or anything requiring SOC2-style dependency hygiene.

Migration path Do not integrate the package directly. Introduce an application-owned boundary first:

  • Define App\Contracts\HtmlRenderer (or PdfRenderer / Screenshotter) with a single render(string $url, array $options): RenderedDocument.
  • Implement PhantomJsRenderer wrapping JonnyW\PhantomJs\Client — configure binary path, timeout, and viewport from config/rendering.php, never at call sites.
  • Inventory existing Client/facade usages and rewrite them against the interface in one pass.
  • Build the second adapter (BrowsershotRenderer over headless Chrome, or a Gotenberg/Puppeteer HTTP sidecar) in parallel.
  • Flip the container binding, not the call sites. Delete the PhantomJS adapter when parity tests pass.

Compatibility Verify explicitly: PHP version constraint, Symfony major version, and whether bin/phantomjs is expected local or system-wide in the installed tag. Confirm the Twig version constraint too — Twig 1.x/2.x pins frequently collide in modern Laravel trees. Treat the package as unusable the moment any of these require a downgrade of a shared dependency.

Sequencing

  1. Confirm the rendering requirement and whether a non-browser renderer (Gotenberg, wkhtmltopdf, Chrome) satisfies it.
  2. Spike the binary in the actual target image; a PhantomJS proof-of-concept on a Mac laptop is not evidence.
  3. Land the renderer interface and refactor call sites against it while still on PhantomJS.
  4. Pin and vendor the binary into a dedicated sidecar container with a fixed base image digest — do not install it on app hosts.
  5. Build a golden-file parity suite (a fixed HTML corpus → expected PDF/page count/text extraction) before the second adapter lands.
  6. Cut over via config flag; keep the old adapter for one release; remove.

Operational Impact

Maintenance Zero upstream maintenance. The package is archived and PhantomJS is archived; any defect is yours. Budget for vendoring the package (or forking under an internal namespace) to patch PHP 8 deprecations, and for owning a pinned binary image indefinitely. This is a permanent headcount tax on a non-differentiating feature.

Support No vendor, no maintainer, no issue triage. The 0-dependents signal means no community to answer questions — internal tribal knowledge only. Any new engineer inheriting the system will need a written runbook covering binary location, version, required OS libraries, and known failure signatures.

Scaling PhantomJS is single-process, heavy (~100–250 MB RSS per render), and leaks memory across renders; it is unsuitable for long-lived workers. Scale horizontally by spawning a process per job, capping concurrency at the worker level (Laravel Horizon maxProcesses + a render-specific queue), and enforcing hard timeouts. Do not attempt pooling or reuse. Throughput will be an order of magnitude below headless Chrome and will degrade silently under memory pressure.

Failure modes Expect: proc_open errors from missing libssl1.0/glibc mismatches; zombie or orphaned processes on timeout; empty or truncated PDFs with a 0 exit code; opaque CLI stderr surfacing as generic exceptions; Twig template errors on options the wrapper doesn't support; and silent hangs on JS-heavy pages because the "wait for" procedure never fires. Every one of these needs a distinct alert, because the default symptom — "no PDF" — does not localize the cause. Wrap all renders with an explicit timeout, an exit-code plus file-size assertion, and a dead-letter path.

Ramp-up Hours to first render; weeks to production confidence. The API is small and well-documented for its era, but debugging is largely reading raw PhantomJS output. Mitigate by front-loading the golden-file test corpus and a diagnostic command (php artisan render:debug --url=...) that dumps the full command string, exit code, stdout, and stderr.

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