thesoftwarefanatics/php-html-parser
A PHP HTML parser for loading, traversing, and manipulating HTML documents. It provides a simple API for extracting elements, attributes, and text, making it useful for scraping, DOM-style processing, and HTML cleanup in PHP applications.
Architecture fit. Unchanged. The package remains a standalone, Composer-installable PHP library with no Laravel coupling — no service provider, no facade, no config file, no publishable assets. Architecturally neutral, but every integration concern is still ours to write: container binding, configuration, error handling, encoding normalization. It lands as a plain library dependency behind a wrapper, not a first-class framework component. The jQuery-style selector API is still the only reason to prefer it over the DOM primitives already available transitively through Symfony components — and 1.8.1 adds no API surface.
Integration feasibility. Mechanically still one composer require. The blocking gate is unchanged and still unresolved by this release: the release notes say nothing about the php constraint, the supported PHP matrix, or Laravel compatibility. The changelog lists six merged PRs, zero issues resolved, and no dependency or platform changes. A patch release that does not touch composer.json's platform requirements cannot clear a PHP 8.1/8.2 floor — so the ten-minute constraint check remains the first action, ahead of any design work. Two new data points sharpen the picture rather than resolve it: (a) two of the merged PRs are Travis CI changes (#6, #20), and Travis CI's open-source tier was wound down years ago — a CI configuration being expanded on Travis is evidence the test matrix is stale, not that it runs on modern PHP; (b) PR #5 adds a string-length guard around is_file(), which is the shape of a defensive fix that often accompanies PHP 8 hardening, but it is one call site, not a compatibility statement. The upstream-divergence question is now more interesting: a 1.8.1 release carrying the same version number as paquettg/php-html-parser's 1.8.1 strongly suggests the fork is resyncing to upstream rather than diverging further. If so, the API surface should now match upstream and upstream docs become more reliable, not less.
Technical risk. Still the dominant section, but the profile has shifted from abandoned to thinly maintained.
Positive signal. Four contributors on this release, including @alcaeus (a Doctrine core maintainer with a public track record) — that is the first evidence of review by someone outside the vendor namespace. Backlog PRs #5–#21 being merged indicates a maintainer is active. Two fixes land directly on risks this assessment previously flagged as unmitigated: #21 (replaceChild) repairs a DOM mutation path, and #7 (charset meta-tag parsing with ; or space after charset) touches exactly the encoding-detection logic behind the charset-mojibake failure mode. That is real, if narrow, progress.
What has not changed. No new dependents, no security advisory coverage, no issue triage (0 issues resolved in this release), no documented support commitment, no PHP 8 declaration. The contributor count is a single release's snapshot, not a maintained roster. PR numbers 5, 6, 7, 18, 20, 21 are low and old — this is backlog clearing, not active development. Six PRs merged is a burst; the question for Q3 is whether a second release follows. Additional risks persist verbatim: UTF-8 mangling unless explicitly coerced, silent truncation on malformed markup, XXE exposure via LIBXML_NOENT, HTML4-era normalization diverging from browser behavior on <template>/custom elements/unclosed tags, and DOM trees costing 5–10× source document size in memory. Note that #7 improves charset detection from meta tags; it does not guarantee UTF-8 output — the mb_convert_encoding normalization requirement stands.
Key questions.
php constraint, and is there any PHP 8.x entry in the CI matrix? The changelog is silent; check composer.json and .travis.yml directly. Still the blocking gate.paquettg/php-html-parser 1.8.1? If the fork has converged, upstream v3 becomes a viable drop-in and the fork's differentiation argument collapses.symfony/dom-crawler + symfony/css-selector satisfy them with maintained security coverage?repositories VCS entry)? The maintenance signal reduces urgency slightly but does not transfer ownership.Stack fit. Unchanged in substance: plausible on Laravel 6–8 with PHP 7.x, high friction on Laravel 10/11, and 1.8.1 provides no new evidence either way. Do not read "six PRs merged" as "PHP 8 ready." Run the composer resolution dry-run against the target application's actual composer.json, not a scratch project, and inspect .travis.yml as part of the same pass — it is the cheapest available proxy for what PHP versions the maintainer believes this code runs on.
Migration path. Recommendation holds: treat symfony/dom-crawler + symfony/css-selector as the baseline and require this package to beat it on a concrete criterion. If the fork has converged on upstream 1.8.1, paquettg/php-html-parser v3 becomes the preferred route to the identical API with a larger user base and a real dependency graph — the fork now has even less reason to be chosen on its own merits. Either way, isolate: define HtmlExtractor (e.g. select(string $html, string $selector): array), implement it in one adapter class owning the third-party namespace, and forbid use of the package elsewhere. A swap to Symfony Crawler or masterminds/html5 stays a one-file change.
Compatibility. Unchanged. Register a singleton in a dedicated HtmlParserServiceProvider (no auto-discovery — nothing to discover). Centralize encoding and LIBXML_* flags in config/html-parser.php. Declare ext-dom and ext-libxml in the platform requirements check. Normalize input to UTF-8 at the adapter boundary — worth re-verifying now that #7 has altered charset detection, since behavior may differ from the version previously tested against.
Sequencing.
.travis.yml matrix + PHP 8 smoke test on the real application manifest (blocking gate).Maintenance. Downgrade from "assume zero" to "assume one part-time maintainer with unverified cadence." That is a meaningful improvement in kind but not in degree: six PRs clearing a multi-year backlog in a single patch release is consistent with a one-off cleanup, and no release cadence or support policy has been published. Ownership of the failure modes still transfers to us. Keep the fork in the internal dependency register with an explicit review date and named owner, and pin exactly with a committed composer.lock — a patch release that changes charset-detection behavior is precisely the kind of change that should not float in unannounced.
Support. Marginally better. @alcaeus's involvement is a credible external reviewer and a name to watch for follow-through; there is still no vendor, no support contract, and no documentation beyond the README. Internal knowledge still concentrates in whoever writes the adapter — bus-factor of one unless a second engineer reviews and the contract tests document expected behavior. Onboarding to the selector API is an hour; onboarding to the DOMDocument and charset edge cases is days.
Scaling. Unchanged. Synchronous, in-process, memory-bound; whole tree materialized with no streaming mode; PHP-FPM memory_limit / queue worker --memory is the practical throughput ceiling. Run batch extraction in queued jobs with chunking and explicit memory guards, not in the request cycle. Cache parsed results across multiple selectors on the same document — re-parsing per selector remains the common accidental performance bug.
Failure modes. The highest-severity one is still PHP upgrade lockout: a stale constraint anchors the next Laravel migration, and this release does not address it. Others: silent truncation on malformed HTML (verify node counts, don't just check for exceptions); charset mojibake — partially mitigated by #7, but detection logic changes are themselves a regression vector, so re-run the fixture corpus rather than assuming improvement; memory exhaustion on oversized documents; XXE exposure if libxml flags are permissive on untrusted HTML; PHP 8 deprecations (dynamic properties, optional-before-required parameters) surfacing as log noise or hard errors — and note that stale Travis CI will not surface these before deployment; and selector semantics diverging from jQuery on sibling/pseudo-class cases, producing subtly wrong extractions that pass review. Add one new watch item: green CI that does not execute is a false assurance signal and should not be counted as test coverage in the risk register.
Ramp-up. Unchanged. Low for the selector API — productive in an hour. Moderate for the operational surface — encoding, libxml flags, memory behavior, and a fixture-driven regression suite are a few days, required regardless of parser choice. Budget it once, not per-package.
How can I help you explore Laravel packages today?