Html\El Builder

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: &lt;script&gt;alert(&quot;xss&quot;)&lt;/script&gt;</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',
    ]));
Placeholder
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);
ComponentVersieJaar
PHP8.42024
Html\El2.02023
Framework\Router1.02025
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 active
HTML-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>