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

Phpquery Single Laravel Package

jaeger/phpquery-single

phpQuery-single is a single-file PHP port of jQuery's DOM API, letting you parse, query, and manipulate HTML/XML using familiar CSS selectors and chainable methods. No extensions or extra dependencies required—just drop it in and go.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. phpQuery is a 2010-era PHP port of jQuery's DOM API: a global pq() function, static class state, and no namespaces, PSR-4 structure, service provider, facade, or contracts. That is structurally at odds with a Laravel application's container-managed, testable architecture. Its legitimate fit is narrow: as a leaf dependency inside an isolated HTML-parsing/scraping layer, behind an adapter interface, never referenced directly from controllers, jobs, or domain services. The static/global state is also a hazard under Laravel Octane, where worker memory persists across requests.

Integration feasibility. Mechanically trivial — composer require and it works, with no configuration, migrations, or bootstrapping. The single-file distribution is actually a modest plus: it is easy to vendor, diff, and patch in-house. In practice it will almost never be a deliberate direct choice; it arrives transitively via jaeger/querylist, which lists it as a dependency. The dataset's "0 dependents" is almost certainly a registry-metadata gap rather than evidence of no consumers — worth confirming against the lockfile before drawing conclusions.

Technical risk. The dominant risk is stewardship, not code quality. Upstream phpQuery has been effectively unmaintained since 0.9.5 (~2010); this fork is a Composer-packaging convenience, not a maintained parser. Consequences:

  • PHP 8.x compatibility is partial — deprecated dynamic properties and removed functions surface as warnings or fatal errors on newer runtimes.
  • Parsing is libxml/HTML4-era; malformed or HTML5 markup can parse differently than a browser or a modern parser would, producing subtly wrong extractions.
  • Memory and character-encoding handling are weak spots on large or non-UTF-8 documents.
  • It parses untrusted HTML; it is a parser, not a sanitizer — do not let it be mistaken for one.

Key questions for the team.

  1. Is this a direct dependency or transitive via QueryList — and can we drop QueryList entirely?
  2. What are the target PHP and Laravel versions, and does the fork run clean on them?
  3. Would symfony/dom-crawler + symfony/css-selector satisfy the same requirement with a maintained codebase?
  4. What is the representative page corpus (size, encoding, malformedness) we must parse?
  5. Do we need selector features beyond jQuery 1.2-era CSS (e.g., :has(), CSS4)?
  6. Who owns patching/forking this if upstream breaks, and what is the license/attribution posture?

Integration Approach

Stack fit. Works with Laravel 10–12 on PHP 8.1+, but only acceptably when confined to an HtmlParser-style contract with a phpQuery-backed implementation. Treat pq() as an implementation detail; nothing outside the adapter should know it exists. This preserves the option to swap in DomCrawler later without touching call sites.

Migration path. Two scenarios:

  • Greenfield scraping: evaluate symfony/dom-crawler + symfony/css-selector first. Adopt phpQuery-single only if QueryList is already mandated by an existing codebase or a specific feature (its jQuery-like manipulation API) is genuinely required.
  • Existing QueryList usage: keep it, but pin exact versions in composer.json, commit the lockfile, and add characterization tests that pin observed behavior so upstream drift is caught rather than discovered in production.

Compatibility. Audit for PHP 8 breakage early — removed functions, dynamic-property deprecations, and implicit nullable parameters are the usual offenders in code of this vintage. CSS selector coverage is jQuery-1.2-era; document the gaps so developers do not write :has() and get silent misses. No namespacing means no autoload conflict risk, but also no ability to run two versions side by side.

Sequencing.

  1. Dependency audit and SBOM entry — establish direct vs transitive and pin.
  2. Spike: run the parser against 20–50 representative real pages; record selector hit rates, encoding failures, and peak memory.
  3. Build the adapter interface plus contract tests; wire the phpQuery implementation behind it.
  4. Isolate all parsing into queue jobs or a dedicated service class with capped input size.
  5. Gate behind a feature flag with a documented rollback to DomCrawler.

Operational Impact

Maintenance. Functionally, this becomes vendored code — assume we own it. Budget recurring effort for PHP-version upgrades and upstream querylist releases that bump the pinned fork. This is low-effort in a quiet year and a sharp, unbudgeted spike during a framework upgrade.

Support. Community-only, no SLA, no CVE feed, no security advisories channel. An internal runbook covering "what to do when parsing breaks" and a named owner are non-optional. Note the license (MIT-lineage) is permissive enough for vendoring and patching.

Scaling. Parsing is CPU- and memory-bound per document and does not parallelize within a request. Mitigations: hard-cap input document size, run parsing in queue workers with tuned memory_limit, and avoid the Octane request path if static state proves to leak across requests. Throughput scales horizontally via workers, not vertically via the library.

Failure modes to instrument.

  • Silent empty selections (selector no longer matches after a target site changes) — the highest-frequency production failure and the hardest to notice; assert on expected non-empty results.
  • libxml warnings polluting output — wrap calls in libxml_use_internal_errors(true).
  • Encoding mojibake on non-UTF-8 sources — normalize input before parsing.
  • Memory exhaustion on oversized documents — enforce a size guard before parse.
  • PHP-version fatal errors after a runtime upgrade — caught by CI matrix, not by production.

Ramp-up. Fast for anyone with jQuery experience — the API is deliberately familiar. The cost is in unlearning assumptions: no live DOM, no event model, global state, and PHP 8-era caveats. Budget roughly half a day of onboarding plus adapter documentation, and make the adapter the reference example so new engineers copy the safe pattern rather than calling pq() directly.

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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings