HTML-Elemente
Die Klasse Nette\Utils\Html ist ein Helfer zur Generierung von HTML-Code, der hilft, Cross-Site-Scripting (XSS)-Schwachstellen zu verhindern.
Sie funktioniert, indem ihre Objekte HTML-Elemente repräsentieren, deren Attribute gesetzt und die dann gerendert werden können:
$el = Html::el('img'); // erstellt das Element <img>
$el->src = 'image.jpg'; // setzt das Attribut src
echo $el; // gibt '<img src="image.jpg">' aus
Installation:
composer require nette/utils
Alle Beispiele setzen voraus, dass der folgende Alias definiert wurde:
use Nette\Utils\Html;
Erstellung von HTML-Elementen
Ein Element wird mit der Methode Html::el()
erstellt:
$el = Html::el('img'); // erstellt das Element <img>
Neben dem Elementnamen können Sie weitere Attribute direkt in HTML-Syntax angeben:
$el = Html::el('input type=text class="red important"');
Oder übergeben Sie sie als assoziatives Array im zweiten Parameter:
$el = Html::el('input', [
'type' => 'text',
'class' => 'important',
]);
Ändern und Abrufen des Elementnamens:
$el->setName('img');
$el->getName(); // 'img'
$el->isEmpty(); // true, da <img> ein leeres Element ist (z.B. <br>, <hr>)
HTML-Attribute
Einzelne HTML-Attribute können auf drei Arten geändert und gelesen werden, es hängt von Ihnen ab, welche Ihnen am besten gefällt. Die erste ist über Properties:
$el->src = 'image.jpg'; // setzt das Attribut src
echo $el->src; // 'image.jpg'
unset($el->src); // entfernt das Attribut
// oder $el->src = null;
Die zweite Möglichkeit ist der Aufruf von Methoden, die – im Gegensatz zum Setzen von Eigenschaften – verkettet werden können:
$el = Html::el('img')->src('image.jpg')->alt('photo');
// <img src="image.jpg" alt="photo">
$el->alt(null); // Attribut entfernen
Und die dritte Möglichkeit ist die ausführlichste:
$el = Html::el('img')
->setAttribute('src', 'image.jpg')
->setAttribute('alt', 'photo');
echo $el->getAttribute('src'); // 'image.jpg'
$el->removeAttribute('alt');
Attribute können gesammelt mit addAttributes(array $attrs)
gesetzt und mit
removeAttributes(array $attrNames)
entfernt werden.
Der Wert eines Attributs muss kein String sein; für boolesche Attribute können auch boolesche Werte verwendet werden:
$checkbox = Html::el('input')->type('checkbox');
$checkbox->checked = true; // <input type="checkbox" checked>
$checkbox->checked = false; // <input type="checkbox">
Ein Attribut kann auch ein Array von Werten sein, die durch Leerzeichen getrennt ausgegeben werden. Dies ist beispielsweise für CSS-Klassen nützlich:
$el = Html::el('input');
$el->class[] = 'active';
$el->class[] = null; // null wird ignoriert
$el->class[] = 'top';
echo $el; // '<input class="active top">'
Eine Alternative ist ein assoziatives Array, bei dem die booleschen Werte angeben, ob der jeweilige Schlüssel als Wert ausgegeben werden soll:
$el = Html::el('input');
$el->class['active'] = true;
$el->class['top'] = false; // wird nicht ausgegeben
echo $el; // '<input class="active">'
CSS-Stile können als assoziatives Array geschrieben werden:
$el = Html::el('input');
$el->style['color'] = 'green';
$el->style['display'] = 'block';
echo $el; // '<input style="color: green; display: block">'
Wir haben eben Eigenschaften verwendet, aber dasselbe kann auch mit Methoden erreicht werden:
$el = Html::el('input');
$el->style('color', 'green');
$el->style('display', 'block');
echo $el; // '<input style="color: green; display: block">'
Oder auf die ausführlichste Weise:
$el = Html::el('input');
$el->appendAttribute('style', 'color', 'green');
$el->appendAttribute('style', 'display', 'block');
echo $el; // '<input style="color: green; display: block">'
Noch eine Anmerkung: Die Methode href()
kann das Zusammenstellen von Query-Parametern in URLs vereinfachen:
echo Html::el('a')->href('index.php', [
'id' => 10,
'lang' => 'en',
]);
// '<a href="index.php?id=10&lang=en"></a>'
Datenattribute
Datenattribute (data-*
) werden besonders unterstützt. Da ihre Namen Bindestriche enthalten, ist der Zugriff über
Eigenschaften und Methoden weniger elegant. Daher gibt es die Methode data()
:
$el = Html::el('input');
$el->{'data-max-size'} = '500x300'; // weniger elegant
$el->data('max-size', '500x300'); // elegant
echo $el; // '<input data-max-size="500x300">'
Wenn der Wert eines Datenattributs ein Array ist, wird er automatisch nach JSON serialisiert:
$el = Html::el('input');
$el->data('items', [1, 2, 3]);
echo $el; // '<input data-items="[1,2,3]">'
Inhalt des Elements
Der innere Inhalt eines Elements wird mit den Methoden setHtml()
oder setText()
festgelegt. Verwenden
Sie setHtml()
nur, wenn Sie sicher sind, dass der übergebene String vertrauenswürdiges HTML enthält.
echo Html::el('span')->setHtml('hello<br>');
// '<span>hello<br></span>'
echo Html::el('span')->setText('10 < 20');
// '<span>10 < 20</span>'
Umgekehrt wird der innere Inhalt mit den Methoden getHtml()
oder getText()
abgerufen. Letztere
entfernt HTML-Tags aus dem Inhalt und konvertiert HTML-Entitäten in die entsprechenden Zeichen.
echo $el->getHtml(); // '10 < 20'
echo $el->getText(); // '10 < 20'
Kindknoten
Der Inhalt eines Elements kann auch ein Array von Kindknoten (Children) sein. Jeder Kindknoten kann entweder ein String oder
ein weiteres Html
-Element sein. Sie werden mit addHtml()
oder addText()
hinzugefügt:
$el = Html::el('span')
->addHtml('hello<br>')
->addText('10 < 20')
->addHtml( Html::el('br') );
// <span>hello<br>10 < 20<br></span>
Eine weitere Möglichkeit, einen neuen Html
-Knoten zu erstellen und hinzuzufügen:
$ul = Html::el('ul');
$ul->create('li', ['class' => 'first'])
->setText('první');
// <ul><li class="first">první</li></ul>
Mit den Kindknoten kann wie mit einem Array gearbeitet werden. Das heißt, man kann auf einzelne Knoten über eckige Klammern
zugreifen, ihre Anzahl mit count()
ermitteln und über sie iterieren:
$el = Html::el('div');
$el[] = '<b>hello</b>';
$el[] = Html::el('span');
echo $el[1]; // '<span></span>'
foreach ($el as $child) { /* ... */ }
echo count($el); // 2
Ein neuer Knoten kann an einer bestimmten Position mit insert(?int $index, $child, bool $replace = false)
eingefügt werden. Wenn $replace = false
ist, wird das Element an der Position $index
eingefügt und die
nachfolgenden Elemente werden verschoben. Wenn $index = null
ist, wird das Element am Ende angefügt.
// Fügt das Element an die erste Position ein und verschiebt die anderen
$el->insert(0, Html::el('span'));
Alle Kindknoten können mit der Methode getChildren()
abgerufen und mit removeChildren()
entfernt
werden.
Erstellung eines Dokumentfragments
Wenn man mit einem Array von Knoten arbeiten möchte, ohne ein umschließendes Element zu benötigen, kann man ein sogenanntes
Dokumentfragment erstellen, indem man null
anstelle eines Elementnamens übergibt:
$el = Html::el(null)
->addHtml('hello<br>')
->addText('10 < 20')
->addHtml( Html::el('br') );
// hello<br>10 < 20<br>
Einen schnelleren Weg zur Erstellung eines Fragments bieten die Methoden fromHtml()
und
fromText()
:
$el = Html::fromHtml('hello<br>');
echo $el; // 'hello<br>'
$el = Html::fromText('10 < 20');
echo $el; // '10 < 20'
Generierung der HTML-Ausgabe
Der einfachste Weg, ein HTML-Element auszugeben, ist die Verwendung von echo
oder die Typumwandlung des Objekts zu
(string)
. Es ist auch möglich, das öffnende Tag, das schließende Tag und die Attribute separat auszugeben:
$el = Html::el('div class=header')->setText('hello');
echo $el; // '<div class="header">hello</div>'
$s = (string) $el; // '<div class="header">hello</div>'
$s = $el->toHtml(); // '<div class="header">hello</div>'
$s = $el->toText(); // 'hello'
echo $el->startTag(); // '<div class="header">'
echo $el->endTag(); // '</div>'
echo $el->attributes(); // 'class="header"'
Ein wichtiges Merkmal ist der automatische Schutz vor Cross-Site-Scripting (XSS). Alle Attributwerte oder
Inhalte, die mit setText()
oder addText()
eingefügt werden, werden zuverlässig maskiert (escaped):
echo Html::el('div')
->title('" onmouseover="bad()')
->setText('<script>bad()</script>');
// <div title='" onmouseover="bad()'><script>bad()</script></div>
Konvertierung HTML ↔ Text
Zur Konvertierung von HTML in reinen Text können Sie die statische Methode htmlToText()
verwenden:
echo Html::htmlToText('<span>One & Two</span>'); // 'One & Two'
HtmlStringable
Das Objekt Nette\Utils\Html
implementiert das Nette\HtmlStringable
-Interface. Dieses Interface wird
beispielsweise von Latte oder Formularen verwendet, um Objekte zu erkennen, deren __toString()
-Methode HTML-Code
zurückgibt. Dadurch wird verhindert, dass der Inhalt doppelt maskiert wird, wenn ein solches Objekt beispielsweise in einer
Vorlage mit {$el}
ausgegeben wird.