HTML elemek
Az Nette\Utils\Html osztály egy segéd a HTML kód generálásához, amely megakadályozza a Cross Site Scripting (XSS) sebezhetőség kialakulását.
Úgy működik, hogy objektumai HTML elemeket képviselnek, amelyeknek paramétereket állítunk be, és kirajzoltatjuk őket:
$el = Html::el('img'); // létrehozza az <img> elemet
$el->src="/?originalUrl=https%3A%2F%2Fdoc.nette.org%2F%26%23039%3Bimage.jpg%26%23039%3B%3B%2520%2F%2F%2520be%25C3%25A1ll%25C3%25ADtja%2520az%2520src%2520attrib%25C3%25BAtumotecho%2520%24el%3B%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2F%2F%2520ki%25C3%25ADrja%3A%2520%26%23039%3B%26lt%3Bimg%2520src%3D%26quot%3Bimage.jpg%26quot%3B%26gt%3B%26%23039%3B%253C%2Fcode">
Telepítés:
composer require nette/utils
Minden példa feltételezi a következő alias létrehozását:
use Nette\Utils\Html;
HTML elem létrehozása
Elemet a Html::el() metódussal hozunk létre:
$el = Html::el('img'); // létrehozza az <img> elemet
A néven kívül megadhat más attribútumokat is HTML szintaxisban:
$el = Html::el('input type=text class="red important"');
Vagy átadhatja őket asszociatív tömbként a második paraméterben:
$el = Html::el('input', [
'type' => 'text',
'class' => 'important',
]);
Az elem nevének megváltoztatása és lekérdezése:
$el->setName('img');
$el->getName(); // 'img'
$el->isEmpty(); // true, mivel az <img> egy üres elem
HTML attribútumok
Az egyes HTML attribútumokat három módon módosíthatjuk és olvashatjuk, Öntől függ, melyik tetszik jobban. Az első a property-ken keresztül történik:
$el->src="/?originalUrl=https%3A%2F%2Fdoc.nette.org%2F%26%23039%3Bimage.jpg%26%23039%3B%3B%2520%2F%2F%2520be%25C3%25A1ll%25C3%25ADtja%2520az%2520src%2520attrib%25C3%25BAtumotecho%2520%24el-%26gt%3Bsrc%3B%2520%2F%2F%2520%26%23039%3Bimage.jpg%26%23039%3Bunset(%24el-%26gt%3Bsrc)%3B%2520%2520%2F%2F%2520t%25C3%25B6rli%2520az%2520attrib%25C3%25BAtumot%2F%2F%2520vagy%2520%24el-%26gt%3Bsrc%2520%3D%2520null%3B%253C%2Fcode">
A második út a metódushívás, amelyek a property-k beállításával ellentétben láncolhatók:
$el = Html::el('img')->src('image.jpg')->alt('photo');
// <img src="/?originalUrl=https%3A%2F%2Fdoc.nette.org%2F%26quot%3Bimage.jpg%26quot%3B%2520alt%3D%26quot%3Bphoto%26quot%3B%26gt%3B%24el-%26gt%3Balt(null)%3B%2520%2F%2F%2520attrib%25C3%25BAtum%2520t%25C3%25B6rl%25C3%25A9se%253C%2Fcode">
A harmadik mód a legbőbeszédűbb:
$el = Html::el('img')
->setAttribute('src', 'image.jpg')
->setAttribute('alt', 'photo');
echo $el->getAttribute('src'); // 'image.jpg'
$el->removeAttribute('alt');
Az attribútumokat tömegesen lehet beállítani az addAttributes(array $attrs) segítségével, és
eltávolítani az removeAttributes(array $attrNames) segítségével.
Az attribútum értéke nem csak string lehet, logikai értékeket is lehet használni logikai attribútumokhoz:
$checkbox = Html::el('input')->type('checkbox');
$checkbox->checked = true; // <input type="checkbox" checked>
$checkbox->checked = false; // <input type="checkbox">
Az attribútum lehet értékek tömbje is, amelyek szóközökkel elválasztva íródnak ki, ami például CSS osztályokhoz hasznos:
$el = Html::el('input');
$el->class[] = 'active';
$el->class[] = null; // a null figyelmen kívül van hagyva
$el->class[] = 'top';
echo $el; // '<input class="active top">'
Alternatíva az asszociatív tömb, ahol az értékek megmondják, hogy a kulcsot ki kell-e írni:
$el = Html::el('input');
$el->class['active'] = true;
$el->class['top'] = false;
echo $el; // '<input class="active">'
A CSS stílusokat asszociatív tömbök formájában lehet írni:
$el = Html::el('input');
$el->style['color'] = 'green';
$el->style['display'] = 'block';
echo $el; // '<input style="color: green; display: block">'
Most property-ket használtunk, de ugyanez leírható metódusokkal is:
$el = Html::el('input');
$el->style('color', 'green');
$el->style('display', 'block');
echo $el; // '<input style="color: green; display: block">'
Vagy akár a legbőbeszédűbb módon is:
$el = Html::el('input');
$el->appendAttribute('style', 'color', 'green');
$el->appendAttribute('style', 'display', 'block');
echo $el; // '<input style="color: green; display: block">'
Még egy apróság a végére: a href() metódus megkönnyítheti a query paraméterek összeállítását az
URL-ben:
echo Html::el('a')->href('index.php', [
'id' => 10,
'lang' => 'en',
]);
// '<a href="/?originalUrl=https%3A%2F%2Fdoc.nette.org%2F%26quot%3Bindex.php%3Fid%3D10%26amp%3Bamp%3Blang%3Den%26quot%3B%26gt%3B%26lt%3B%2Fa%26gt%3B%26%23039%3B%253C%2Fcode">
Data attribútumok
A data attribútumok speciális támogatást élveznek. Mivel nevük kötőjeleket tartalmaz, a property-ken és metódusokon
keresztüli hozzáférés nem olyan elegáns, ezért létezik a data() metódus:
$el = Html::el('input');
$el->{'data-max-size'} = '500x300'; // nem annyira elegáns
$el->data('max-size', '500x300'); // elegáns
echo $el; // '<input data-max-size="500x300">'
Ha a data attribútum értéke tömb, automatikusan JSON-ba szerializálódik:
$el = Html::el('input');
$el->data('items', [1,2,3]);
echo $el; // '<input data-items="[1,2,3]">'
Elem tartalma
Az elem belső tartalmát a setHtml() vagy setText() metódusokkal állítjuk be. Az elsőt csak
abban az esetben használja, ha biztosan tudja, hogy a paraméterben megbízhatóan biztonságos HTML stringet ad át.
echo Html::el('span')->setHtml('hello<br>');
// '<span>hello<br></span>'
echo Html::el('span')->setText('10 < 20');
// '<span>10 < 20</span>'
És fordítva, a belső tartalmat a getHtml() vagy getText() metódusokkal kapjuk meg. A második
eltávolítja a HTML tageket a kimenetből, és a HTML entitásokat karakterekké konvertálja.
echo $el->getHtml(); // '10 < 20'
echo $el->getText(); // '10 < 20'
Gyermek csomópontok
Az elem belseje lehet gyermek (children) csomópontok tömbje is. Mindegyikük lehet string vagy egy másik Html
elem. Az addHtml() vagy addText() segítségével illesztjük be őket:
$el = Html::el('span')
->addHtml('hello<br>')
->addText('10 < 20')
->addHtml( Html::el('br') );
// <span>hello<br>10 < 20<br></span>
Egy másik mód új Html csomópont létrehozására és beillesztésére:
$ul = Html::el('ul');
$ul->create('li', ['class' => 'first'])
->setText('első');
// <ul><li class="first">első</li></ul>
A csomópontokkal ugyanúgy lehet dolgozni, mintha tömbről lenne szó. Azaz hozzáférni az egyes elemekhez szögletes
zárójelekkel, megszámolni őket a count() segítségével, és iterálni rajtuk:
$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
Új csomópontot lehet egy konkrét helyre beilleszteni az insert(?int $index, $child, bool $replace = false)
segítségével. Ha a $replace = false, beilleszti az elemet az $index pozícióra, és a többit
eltolja. Ha az $index = null, hozzáadja az elemet a végére.
// beilleszti az elemet az első pozícióra és a többit eltolja
$el->insert(0, Html::el('span'));
Az összes csomópontot a getChildren() metódussal kapjuk meg, és eltávolítjuk őket a
removeChildren() metódussal.
Dokumentum fragmentum létrehozása
Ha csomópontok tömbjével akarunk dolgozni, és nem érdekel minket a burkoló elem, létrehozhatunk egy ún. dokumentum
fragmentumot null átadásával az elem neve helyett:
$el = Html::el(null)
->addHtml('hello<br>')
->addText('10 < 20')
->addHtml( Html::el('br') );
// hello<br>10 < 20<br>
Gyorsabb módot kínálnak a fragmentum létrehozására a fromHtml() és fromText() metódusok:
$el = Html::fromHtml('hello<br>');
echo $el; // 'hello<br>'
$el = Html::fromText('10 < 20');
echo $el; // '10 < 20'
HTML kimenet generálása
A legegyszerűbb módja egy HTML elem kiírásának az echo használata vagy az objektum
(string)-gé típuskonvertálása. Külön is kiírhatók a nyitó vagy záró tagek és attribútumok:
$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"'
Fontos jellemző az automatikus védelem a Cross Site
Scripting (XSS) ellen. Minden attribútumérték vagy a setText() vagy addText() keresztül
beillesztett tartalom megbízhatóan escapelve van:
echo Html::el('div')
->title('" onmouseover="bad()')
->setText('<script>bad()</script>');
// <div title='" onmouseover="bad()'><script>bad()</script></div>
HTML ↔ Szöveg konverzió
HTML szöveggé alakításához használhatja a htmlToText() statikus metódust:
echo Html::htmlToText('<span>One & Two</span>'); // 'One & Two'
HtmlStringable
A Nette\Utils\Html objektum implementálja a Nette\HtmlStringable interfészt, amellyel például a
Latte vagy az űrlapok megkülönböztetik azokat az objektumokat, amelyek rendelkeznek a __toString() metódussal,
amely HTML kódot ad vissza. Így nem történik dupla escapelés, ha például az objektumot kiírjuk a sablonban a
{$el} segítségével.