Html\El — de HTML-builder
El is een fluent, chainable API om HTML te bouwen zonder string-concatenatie of templates. Escaping is standaard ingebakken via text(); raw() is opt-in.
Basistag
El::make() maakt een element. Tekst via ->text() (escaped), attributen via 2e parameter.
return (string) El::make('a', ['href' => '/home', 'class' => 'btn'])
->text('Klik hier');HTML-source
<a class="btn" href="/home">Klik hier</a>Nesting met add()
add() voegt kinderen toe en geeft $this terug — chainable.
return (string) El::make('ul')
->add(El::make('li')->text('Item 1'))
->add(El::make('li')->text('Item 2'))
->add(El::make('li')->text('Item 3'));- Item 1
- Item 2
- Item 3
HTML-source
<ul><li>Item 1</li><li>Item 2</li><li>Item 3</li></ul>Attributen, classes, data-*
attr() zet een attribuut, addClass() voegt CSS-classes toe, data() stuurt data-attributen.
$el = El::make('button')->text('Opslaan');
$el->attr('type', 'submit');
$el->addClass('btn', 'btn-primary');
$el->data('action', 'save');
return (string) $el;HTML-source
<button class="btn btn-primary" type="submit" data-action="save">Opslaan</button>XSS-veilig: text() escaped, raw() vertrouwt
Gebruik altijd text() voor user-input. raw() alleen voor vertrouwde HTML-strings.
$userInput = '<script>alert("xss")</script>';
return (string) El::make('div')
->add(El::make('p')->text('Escaped: ' . $userInput))
->add(El::make('p')->raw('Vertrouwd: <strong>OK</strong>'));Escaped: <script>alert("xss")</script>
Vertrouwd: OK
HTML-source
<div><p>Escaped: <script>alert("xss")</script></p><p>Vertrouwd: <strong>OK</strong></p></div>Void-elementen sluiten zichzelf
br, hr, img, input — geen </br>-bugs ooit. (Demo gebruikt placehold.co zodat je de img écht ziet.)
return (string) El::make('div')
->add(El::make('img', ['src' => 'https://placehold.co/120x40', 'alt' => 'Placeholder']))
->add(El::make('hr'))
->add(El::make('input', [
'type' => 'text',
'placeholder' => 'Naam',
'style' => 'display:block;margin-top:8px',
]));HTML-source
<div><img src="https://placehold.co/120x40" alt="Placeholder"><hr><input style="display: block; margin-top: 8px" type="text" placeholder="Naam"></div>Tabel bouwen via loops
Structurele HTML is veel leesbaarder dan string-concat.
$data = [
['PHP', '8.4', '2024'],
['Html\\El', '2.0', '2023'],
['Framework\\Router', '1.0', '2025'],
];
$table = El::make('table', ['class' => 'demo-table']);
$thead = El::make('thead');
$tr = El::make('tr');
foreach (['Component', 'Versie', 'Jaar'] as $h) {
$tr->add(El::make('th')->text($h));
}
$thead->add($tr);
$table->add($thead);
$tbody = El::make('tbody');
foreach ($data as $row) {
$tr = El::make('tr');
foreach ($row as $cell) {
$tr->add(El::make('td')->text($cell));
}
$tbody->add($tr);
}
return (string) $table->add($tbody);| Component | Versie | Jaar |
|---|---|---|
| PHP | 8.4 | 2024 |
| Html\El | 2.0 | 2023 |
| Framework\Router | 1.0 | 2025 |
HTML-source
<table class="demo-table"><thead><tr><th>Component</th><th>Versie</th><th>Jaar</th></tr></thead><tbody><tr><td>PHP</td><td>8.4</td><td>2024</td></tr><tr><td>Html\El</td><td>2.0</td><td>2023</td></tr><tr><td>Framework\Router</td><td>1.0</td><td>2025</td></tr></tbody></table>classList — DOM-stijl API
add, remove, toggle, contains, replace — net als window.Element.classList.
$el = El::make('div');
$el->classList->add('btn', 'btn-primary');
$el->classList->toggle('active');
$el->classList->replace('btn-primary', 'btn-secondary');
// Output wordt in een <code> gewikkeld zodat de string-waarde
// zichtbaar is in plaats van een lege <div class="...">.
return '<code>' . htmlspecialchars((string) $el->classList) . '</code>';btn btn-secondary activeHTML-source
<code>btn btn-secondary active</code>DOM-traversal: fromHtml + find
fromHtml() parsed een fragment; first() / find() / childAt() lijken op de browser-API.
$frag = El::fromHtml('<ul><li class="item">A</li><li class="item">B</li></ul>');
$items = $frag->first('ul')->find('.item'); // ElCollection
$items->addClass('highlight');
return (string) $frag;- A
- B
HTML-source
<ul><li class="item highlight">A</li><li class="item highlight">B</li></ul>