Elemente HTML
Clasa Nette\Utils\Html este un ajutor pentru generarea codului HTML care previne vulnerabilitatea Cross Site Scripting (XSS).
Funcționează astfel: obiectele sale reprezintă elemente HTML cărora le setăm atributele și apoi le randăm:
$el = Html::el('img'); // creează elementul <img>
$el->src = 'image.jpg'; // setează atributul src
echo $el; // afișează '<img src="image.jpg">'
Instalare:
composer require nette/utils
Toate exemplele presupun că a fost creat un alias:
use Nette\Utils\Html;
Crearea unui element HTML
Elementul se creează folosind metoda Html::el()
:
$el = Html::el('img'); // creează elementul <img>
Pe lângă nume, puteți specifica și alte atribute folosind sintaxa HTML:
$el = Html::el('input type=text class="red important"');
Sau le puteți transmite ca array asociativ în al doilea parametru:
$el = Html::el('input', [
'type' => 'text',
'class' => 'important',
]);
Modificarea și obținerea numelui elementului:
$el->setName('img');
$el->getName(); // 'img'
$el->isEmpty(); // true, deoarece <img> este un element gol
Atribute HTML
Atributele HTML individuale pot fi setate și citite în trei moduri; depinde de dvs. care preferați. Primul mod este prin proprietăți:
$el->src = 'image.jpg'; // setează atributul src
echo $el->src; // 'image.jpg'
unset($el->src); // elimină atributul
// sau $el->src = null;
Al doilea mod este prin apelarea metodelor, care, spre deosebire de setarea proprietăților, pot fi înlănțuite:
$el = Html::el('img')->src('image.jpg')->alt('photo');
// <img src="image.jpg" alt="photo">
$el->alt(null); // eliminarea atributului
Și al treilea mod este cel mai verbos:
$el = Html::el('img')
->setAttribute('src', 'image.jpg')
->setAttribute('alt', 'photo');
echo $el->getAttribute('src'); // 'image.jpg'
$el->removeAttribute('alt');
Atributele pot fi setate în bloc folosind addAttributes(array $attrs)
și eliminate folosind
removeAttributes(array $attrNames)
.
Valoarea atributului nu trebuie să fie doar un șir; se pot folosi și valori booleene pentru atributele booleene:
$checkbox = Html::el('input')->type('checkbox');
$checkbox->checked = true; // <input type="checkbox" checked>
$checkbox->checked = false; // <input type="checkbox">
Atributul poate fi și un array de valori, care se afișează separate prin spații, util, de exemplu, pentru clasele CSS:
$el = Html::el('input');
$el->class[] = 'active';
$el->class[] = null; // null este ignorat
$el->class[] = 'top';
echo $el; // '<input class="active top">'
O alternativă este un array asociativ, unde valorile indică dacă cheia trebuie afișată:
$el = Html::el('input');
$el->class['active'] = true;
$el->class['top'] = false;
echo $el; // '<input class="active">'
Stilurile CSS pot fi scrise sub formă de array-uri asociative:
$el = Html::el('input');
$el->style['color'] = 'green';
$el->style['display'] = 'block';
echo $el; // '<input style="color: green; display: block">'
Am folosit proprietăți, dar același lucru se poate scrie folosind metode:
$el = Html::el('input');
$el->style('color', 'green');
$el->style('display', 'block');
echo $el; // '<input style="color: green; display: block">'
Sau chiar în modul cel mai verbos:
$el = Html::el('input');
$el->appendAttribute('style', 'color', 'green');
$el->appendAttribute('style', 'display', 'block');
echo $el; // '<input style="color: green; display: block">'
Un mic detaliu la final: metoda href()
poate facilita compunerea parametrilor query în URL:
echo Html::el('a')->href('index.php', [
'id' => 10,
'lang' => 'en',
]);
// '<a href="index.php?id=10&lang=en"></a>'
Atribute data-*
Atributele data-* (data attributes) au un suport special. Deoarece numele lor conțin cratime, accesul prin proprietăți și
metode nu este la fel de elegant, de aceea există metoda data()
:
$el = Html::el('input');
$el->{'data-max-size'} = '500x300'; // nu este la fel de elegant
$el->data('max-size', '500x300'); // este elegant
echo $el; // '<input data-max-size="500x300">'
Dacă valoarea unui atribut data-* este un array, acesta se serializează automat în JSON:
$el = Html::el('input');
$el->data('items', [1, 2, 3]);
echo $el; // '<input data-items="[1,2,3]">'
Conținutul elementului
Conținutul intern al elementului se setează cu metodele setHtml()
sau setText()
. Folosiți
setHtml()
doar dacă sunteți sigur că parametrul conține un șir HTML sigur.
echo Html::el('span')->setHtml('hello<br>');
// '<span>hello<br></span>'
echo Html::el('span')->setText('10 < 20');
// '<span>10 < 20</span>'
Invers, conținutul intern se obține cu metodele getHtml()
sau getText()
. getText()
elimină tag-urile HTML din conținut și convertește entitățile HTML în caractere.
echo $el->getHtml(); // '10 < 20'
echo $el->getText(); // '10 < 20'
Noduri copil
Conținutul unui element poate fi, de asemenea, un array de noduri copil (children). Fiecare nod poate fi fie un șir, fie un
alt element Html
. Le adăugăm folosind addHtml()
sau addText()
:
$el = Html::el('span')
->addHtml('hello<br>')
->addText('10 < 20')
->addHtml( Html::el('br') );
// <span>hello<br>10 < 20<br></span>
Altă modalitate de a crea și insera un nou nod Html
:
$ul = Html::el('ul');
$ul->create('li', ['class' => 'first'])
->setText('primul');
// <ul><li class="first">primul</li></ul>
Cu nodurile se poate lucra la fel ca și cu un array. Adică, accesarea individuală a acestora folosind paranteze drepte,
numărarea lor folosind count()
și iterarea peste ele:
$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
Un nod nou poate fi inserat într-o poziție specifică folosind
insert(?int $index, $child, bool $replace = false)
. Dacă $replace
este false
, inserează
elementul la poziția $index
și le deplasează pe celelalte. Dacă $index
este null
,
adaugă elementul la sfârșit.
// inserează elementul la prima poziție și le deplasează pe celelalte
$el->insert(0, Html::el('span'));
Toate nodurile copil se obțin cu metoda getChildren()
și se elimină cu metoda
removeChildren()
.
Crearea unui fragment de document
Dacă dorim să lucrăm cu un array de noduri fără un element înconjurător, putem crea un fragment de document
transmițând null
în loc de numele elementului:
$el = Html::el(null)
->addHtml('hello<br>')
->addText('10 < 20')
->addHtml( Html::el('br') );
// hello<br>10 < 20<br>
Metodele fromHtml()
și fromText()
oferă o modalitate mai rapidă de a crea un fragment:
$el = Html::fromHtml('hello<br>');
echo $el; // 'hello<br>'
$el = Html::fromText('10 < 20');
echo $el; // '10 < 20'
Generarea ieșirii HTML
Cel mai simplu mod de a afișa un element HTML este să folosiți echo
sau să convertiți obiectul la
(string)
. Se pot, de asemenea, afișa separat tag-urile de deschidere sau închidere și atributele:
$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"'
O caracteristică importantă este protecția automată împotriva Cross Site Scripting (XSS). Toate valorile atributelor
sau conținutul inserat prin setText()
sau addText()
sunt escapate în mod fiabil:
echo Html::el('div')
->title('" onmouseover="bad()')
->setText('<script>bad()</script>');
// <div title='" onmouseover="bad()'><script>bad()</script></div>
Conversie HTML ↔ text
Pentru a converti HTML în text, puteți utiliza metoda statică htmlToText()
:
echo Html::htmlToText('<span>One & Two</span>'); // 'One & Two'
HtmlStringable
Obiectul Nette\Utils\Html
implementează interfața Nette\HtmlStringable
. Latte și formularele
folosesc această interfață pentru a distinge obiectele care au o metodă __toString()
ce returnează cod HTML.
Astfel, nu se produce dublă escapare dacă, de exemplu, afișăm obiectul într-un șablon folosind {$el}
.