Elemente HTML
Clasa Nette\Utils\Html este un ajutor pentru generarea codului HTML care nu permite apariția vulnerabilității Cross Site Scripting (XSS).
Funcționează astfel încât obiectele sale reprezintă elemente HTML cărora le setăm parametrii și le lăsăm să se randeze:
$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 crearea unui alias:
use Nette\Utils\Html;
Crearea unui element HTML
Elementul se creează prin metoda Html::el()
:
$el = Html::el('img'); // creează elementul <img>
Pe lângă nume, puteți specifica și alte atribute în 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 returnarea numelui elementului:
$el->setName('img');
$el->getName(); // 'img'
$el->isEmpty(); // true, deoarece <img> este un element gol
Atribute HTML
Atributele HTML individuale pot fi modificate și citite în trei moduri, depinde de dvs. care vă place mai mult. Primul este prin proprietăți:
$el->src = 'image.jpg'; // setează atributul src
echo $el->src; // 'image.jpg'
unset($el->src); // anulează atributul
// sau $el->src = null;
A doua cale este apelarea metodelor, care, spre deosebire de setarea proprietăților, pot fi înșiruite:
$el = Html::el('img')->src('image.jpg')->alt('photo');
// <img src="image.jpg" alt="photo">
$el->alt(null); // anularea atributului
Și a treia modalitate este cea mai verbioasă:
$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 masă folosind addAttributes(array $attrs)
și eliminate folosind
removeAttributes(array $attrNames)
.
Valoarea atributului nu trebuie să fie doar un șir, se pot folosi și valori logice pentru atributele logice:
$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, ceea ce este util, de exemplu, pentru clasele CSS:
$el = Html::el('input');
$el->class[] = 'active';
$el->class[] = null; // null se ignoră
$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">'
Acum 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 verbios:
$el = Html::el('input');
$el->appendAttribute('style', 'color', 'green');
$el->appendAttribute('style', 'display', 'block');
echo $el; // '<input style="color: green; display: block">'
Încă 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 de date
Atributele de date au un suport special. Deoarece numele lor conțin cratime, accesul prin proprietăți și metode nu este
atât de elegant, de aceea există metoda data()
:
$el = Html::el('input');
$el->{'data-max-size'} = '500x300'; // nu este atât de elegant
$el->data('max-size', '500x300'); // este elegant
echo $el; // '<input data-max-size="500x300">'
Dacă valoarea atributului de date 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()
. Prima o folosiți
doar dacă știți că în parametru transmiteți un șir HTML sigur în mod fiabil.
echo Html::el('span')->setHtml('hello<br>');
// '<span>hello<br></span>'
echo Html::el('span')->setText('10 < 20');
// '<span>10 < 20</span>'
Și invers, conținutul intern se obține cu metodele getHtml()
sau getText()
. A doua elimină din
ieșire tag-urile HTML și convertește entitățile HTML în caractere.
echo $el->getHtml(); // '10 < 20'
echo $el->getText(); // '10 < 20'
Noduri copil
Interiorul elementului poate fi, de asemenea, un array de noduri copil (children). Fiecare dintre acestea poate fi fie un șir,
fie un alt element Html
. Le inseră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 cum ar fi 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-un loc specific folosind insert(?int $index, $child, bool $replace = false)
.
Dacă $replace = false
, inserează elementul la poziția $index
și le deplasează pe celelalte. Dacă
$index = null
, adaugă elementul la sfârșit.
// inserează elementul pe prima poziție și le deplasează pe celelalte
$el->insert(0, Html::el('span'));
Toate nodurile 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 și nu ne interesează elementul înconjurător, putem crea așa-numitul
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>
O modalitate mai rapidă de a crea un fragment este oferită de metodele fromHtml()
și
fromText()
:
$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
, prin care, de exemplu,
Latte sau formularele disting obiectele care au metoda __toString()
returnând cod HTML. Astfel, nu se produce dublă
escapare dacă, de exemplu, afișăm obiectul într-un șablon folosind {$el}
.