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

Extended Htmldocument Laravel Package

vardumper/extended-htmldocument

ExtendedHtmlDocument is a PHP library that extends DOMDocument with convenient helpers for loading, querying, and manipulating HTML. It reduces boilerplate for common DOM tasks, making it easier to find elements, traverse markup, and apply changes in scraping or transformation workflows.

View on GitHub
Deep Wiki
Context7

Getting Started

vardumper/extended-htmldocument wraps PHP 8.4's native Dom\HTMLDocument (the new HTML5 spec-compliant parser) and adds the conveniences you actually want in application code: CSS selector queries (querySelector / querySelectorAll), XPath, and a cleaner element API. It is framework-agnostic but drops neatly into a Laravel app for scraping, sanitizing, and asserting on HTML.

Minimal steps:

  1. Confirm PHP 8.4+ (php -v). The package relies on Dom\HTMLDocument, so it will not install/run on lower PHP versions.
  2. composer require vardumper/extended-htmldocument
  3. Parse and query:
use Vardumper\ExtendedHtmlDocument\ExtendedHtmlDocument;

$doc = ExtendedHtmlDocument::createFromString($html);

$title = $doc->querySelector('h1.title')?->textContent;
$links = $doc->querySelectorAll('a[rel="nofollow"]');
  • First place to look: the README's usage section and the ExtendedHtmlDocument class itself — it's a thin layer over Dom\HTMLDocument, so the underlying DOM API is your reference for anything not wrapped.
  • First meaningful use case: a queued job or artisan command that fetches a page via Http::get() and extracts a handful of fields with CSS selectors instead of brittle regex or regex-adjacent str_* calls.

Implementation Patterns

Selector-based extraction in a service. Keep DOM work out of controllers; wrap it in a small service or a HtmlExtractor class that accepts a string and returns a DTO. This is testable and keeps the parser detail swappable.

final class ProductPageParser
{
    public function parse(string $html): ProductData
    {
        $doc = ExtendedHtmlDocument::createFromString($html);

        return new ProductData(
            name: $doc->querySelector('h1[itemprop="name"]')?->textContent,
            price: $doc->querySelector('.price')?->textContent,
            images: array_map(
                fn ($el) => $el->getAttribute('src'),
                iterator_to_array($doc->querySelectorAll('.gallery img'))
            ),
        );
    }
}

Pairing with the HTTP client. Http::get($url)->body() feeds directly into createFromString(). Use retry(), timeouts, and ->throw() on the client so the parser only ever sees real HTML.

Parsing files and fixtures. For uploaded/generated HTML, use createFromFile($path) where available, or file_get_contents() + createFromString(). In feature tests, store representative HTML as fixtures and assert on extracted values rather than on raw markup strings.

Rendering checks in tests. For Blade output assertions, parse the rendered string and query it — assertSee only does substring matching, whereas selector queries prove structure:

$doc = ExtendedHtmlDocument::createFromString($this->get('/')->getContent());
$this->assertNotNull($doc->querySelector('nav a[aria-current="page"]'));

Sanitization/rewriting workflows. Because you get a real DOM tree, you can walk it, mutate nodes, and serialize back out — useful for stripping elements or rewriting links before storing content.

XPath for the cases CSS can't express. Fall back to XPath when you need predicates on text content, sibling axes, or namespaced attributes; CSS selectors cover the common 90%.

Gotchas and Tips

  • PHP 8.4 is a hard floor. This is the single biggest gotcha. If your CI matrix or production runtime is on 8.2/8.3, the package is a non-starter. Check platform in composer.json and your Docker base image before adopting.
  • Pre-1.0 semver. You're on 0.3.x. Patch releases like 0.3.5 carry no documented breaking changes per the changelog, but the 0.x line gives no compatibility guarantee across minor bumps — pin the version in composer.json and read changelogs on every minor upgrade.
  • Sparse release notes. 0.3.5 ships no descriptive notes beyond a compare link. Before bumping, diff 0.3.4...0.3.5 on GitHub or run your test suite against the new tag; treat patch bumps as low-risk but not zero-risk on a 0.x package.
  • HTML5 parser vs. legacy DOMDocument. Dom\HTMLDocument follows HTML5 error-recovery rules, so malformed markup parses differently than DOMDocument/libxml_use_internal_errors. Don't assume identical node trees if migrating existing code.
  • querySelector returns null. Always null-safe-chain (?->textContent) — a missing selector is silent, not an exception. For required fields, validate explicitly and throw a domain exception so scraping drift fails loudly rather than silently storing nulls.
  • querySelectorAll ergonomics. It's not a foreach-friendly live list in every version — wrap with iterator_to_array() or foreach carefully depending on the return type, and avoid relying on live-updating node lists after mutation.
  • CSS selector gaps. The selector support is driven by Symfony CssSelector under the hood; pseudo-classes like :has() or newer CSS4 selectors may be unsupported. Fall back to XPath (queryXPath) when a selector silently returns nothing.
  • Encoding. Ensure your source is UTF-8 before parsing (HTTP client + mb_convert_encoding if needed). The parser honors declared charsets, but inconsistent encoding is a classic source of mangled textContent.
  • Memory on large documents. The whole tree is in memory. For big pages or bulk scraping, process per-page and let the document go out of scope; don't accumulate DOM objects in a collection.
  • Remote content trust. Parsing third-party HTML in-process is generally fine, but keep the parser behind your HTTP client's timeout/redirect limits and never eval or execute anything from parsed nodes.
  • Extension points. Since it's a thin wrapper, subclass or compose it for app-specific helpers (e.g. textOf(string $selector) convenience methods) rather than forking the package.
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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons