paquettg/php-html-parser
Fast, lightweight HTML parser for PHP that turns messy markup into a DOM-like tree. Crawl and scrape pages, query elements with CSS selectors, and extract text/attributes easily. Works with imperfect HTML and focuses on simple, fluent usage.
Installation
composer require paquettg/php-html-parser
No additional configuration is needed—just require the package in your project.
First Use Case: Parsing HTML
use PHPHtmlParser\Dom;
$html = '<div class="example"><h1>Hello</h1><p>World</p></div>';
$dom = new Dom();
$dom->loadFromString($html);
// Extract the h1 text
echo $dom->find('h1', 0)->text; // Output: "Hello"
Where to Look First
Dom class methods: loadFromString(), loadFromFile(), find(), getAttribute(), setAttribute(), etc.'div.example', 'h1 > p').Scraping Web Pages
$dom = new Dom();
$dom->loadFromUrl('https://example.com');
// Extract all links
$links = $dom->find('a');
foreach ($links as $link) {
echo $link->href . "\n";
}
Modifying HTML
$dom = new Dom();
$dom->loadFromString('<div id="old">Old Content</div>');
// Update content and attributes
$dom->find('div', 0)->setAttribute('id', 'new');
$dom->find('div', 0)->text = 'New Content';
echo $dom->saveHtml(); // Output: '<div id="new">New Content</div>'
Dynamic Selectors with Data Attributes
$dom->loadFromString('<div data-id="123">Item</div>');
$item = $dom->find('[data-id="123"]', 0);
echo $item->text; // Output: "Item"
Iterating and Filtering Nodes
$dom->loadFromString('<ul><li>Apple</li><li>Banana</li><li>Cherry</li></ul>');
$fruits = $dom->find('li');
// Filter fruits starting with 'B'
$bananas = array_filter($fruits, fn($node) => str_starts_with($node->text, 'B'));
Handling Forms
$dom->loadFromString('<form><input name="email" value="test@example.com"></form>');
$email = $dom->find('input[name="email"]', 0)->getAttribute('value');
Str::of() with PHPHtmlParser for dynamic HTML manipulation in Blade templates.
use Illuminate\Support\Str;
use PHPHtmlParser\Dom;
$html = '<div class="content">...</div>';
$dom = new Dom();
$dom->loadFromString($html);
// Modify HTML in Blade
echo Str::of($dom->saveHtml())->replace('content', 'updated-content');
Dom objects for performance-critical scraping tasks.
$cacheKey = 'parsed_html_' . md5($url);
$dom = Cache::remember($cacheKey, now()->addHours(1), function() use ($url) {
$dom = new Dom();
$dom->loadFromUrl($url);
return $dom;
});
Selector Limitations
:nth-child(odd)) may not work as expected. Test selectors thoroughly.find() with loops and manual filtering if needed.Malformed HTML
loadFromString() with Dom::PARSER_HTML flag for strict parsing:
$dom->loadFromString($html, Dom::PARSER_HTML);
Attribute Case Sensitivity
class or for are case-insensitive in HTML but may behave differently in selectors. Stick to lowercase for consistency.Memory Usage
loadFromUrl() with streaming or chunking for large files.XPath vs. Selectors
DOMXPath:
$xpath = new DOMXPath($dom->getDOM());
$nodes = $xpath->query('//div[@class="complex"]');
saveHtml() to debug the current state of the DOM:
echo $dom->saveHtml(); // Log or dump this for debugging
try {
$dom->loadFromUrl($url);
} catch (\Exception $e) {
Log::error("Failed to parse URL: {$url}", ['error' => $e->getMessage()]);
}
Custom Selector Logic
Extend the parser by implementing your own selector logic using Dom::find() and array filtering:
$customNodes = array_filter($dom->find('*'), function($node) {
return str_contains($node->className, 'custom-class');
});
Event Listeners
Hook into the parsing process by overriding the Dom class or using traits for pre/post-processing:
class CustomDom extends Dom {
public function loadFromString($string, $parser = null) {
$this->preProcess($string);
parent::loadFromString($string, $parser);
}
private function preProcess($html) {
// Modify HTML before parsing (e.g., add missing tags)
}
}
Integration with Laravel Events Dispatch events after parsing or modifying HTML:
event(new HtmlParsed($dom, $url));
Performance Optimization
Dom instances instead of recreating them.loadFromFile() for static HTML files to avoid re-downloading content.How can I help you explore Laravel packages today?