HTML Elemanları

Nette\Utils\Html sınıfı, HTML kodu üretmeye yarayan ve Cross-Site Scripting (XSS) açıklarını önlemeye yardımcı olan bir araçtır.

Çalışma biçimi şudur: nesneleri HTML elemanlarını temsil eder; parametrelerini ayarlar, sonra render edersiniz:

$el = Html::el('img');  // <img> elemanı oluşturur
$el->src = 'image.jpg'; // src niteliğini ayarlar
echo $el;               // '<img src="image.jpg">' yazdırır

Bir elemanın gövdesini add() metoduyla metin ve başka elemanlarla doldurabilirsiniz. Metin otomatik olarak kaçışlanır, elemanlar olduğu gibi eklenir:

echo Html::el('div')->add(
	'Hello ',
	Html::el('b')->setText('world'),
);
// '<div>Hello <b>world</b></div>'

Kurulum:

composer require nette/utils

Tüm örnekler, aşağıdaki sınıf takma adının tanımlandığını varsayar:

use Nette\Utils\Html;

HTML Elemanı Oluşturma

Eleman Html::el() metoduyla oluşturulur:

$el = Html::el('img'); // <img> elemanı oluşturur

Adın yanı sıra, HTML söz dizimini kullanarak başka nitelikler de belirtebilirsiniz:

$el = Html::el('input type=text class="red important"');

Ya da bunları ikinci parametrede ilişkisel dizi olarak verebilirsiniz:

$el = Html::el('input', [
	'type' => 'text',
	'class' => 'important',
]);

Elemanın adını değiştirmek ve almak için:

$el->setName('img');
$el->getName(); // 'img'
$el->isEmpty(); // true, çünkü <img> içeriksiz bir elemandır

HTML Nitelikleri

Tek tek HTML nitelikleri üç yolla ayarlanıp alınabilir; hangisini yeğleyeceğiniz size kalmış. Birincisi özellikler üzerinden:

$el->src = 'image.jpg'; // src niteliğini ayarlar

echo $el->src; // 'image.jpg'

unset($el->src);  // niteliği kaldırır
// ya da $el->src = null;

İkinci yol, özellik ayarlamanın aksine zincirlenebilen metot çağrılarıdır:

$el = Html::el('img')->src('image.jpg')->alt('photo');
// <img src="image.jpg" alt="photo">

$el->alt(null); // niteliği kaldırır

Üçüncü yol ise en ayrıntılı olanıdır:

$el = Html::el('img')
	->setAttribute('src', 'image.jpg')
	->setAttribute('alt', 'photo');

echo $el->getAttribute('src'); // 'image.jpg'

$el->removeAttribute('alt');

Nitelikler addAttributes(array $attrs) ile toplu olarak ayarlanabilir, removeAttributes(array $attrNames) ile kaldırılabilir.

Bir niteliğin değeri yalnızca dize olmak zorunda değildir; boolean nitelikler için boolean değerler kullanılabilir:

$checkbox = Html::el('input')->type('checkbox');
$checkbox->checked = true;  // <input type="checkbox" checked>
$checkbox->checked = false; // <input type="checkbox">

Bir nitelik, boşlukla ayrılmış olarak çıktılanan değerlerden oluşan bir dizi de olabilir. Bu, örneğin CSS sınıfları için kullanışlıdır:

$el = Html::el('input');
$el->class[] = 'active';
$el->class[] = null; // null yok sayılır
$el->class[] = 'top';
echo $el; // '<input class="active top">'

Bir alternatif de, değerlerin anahtarın dahil edilip edilmeyeceğini belirttiği ilişkisel dizidir:

$el = Html::el('input');
$el->class['active'] = true;
$el->class['top'] = false;
echo $el; // '<input class="active">'

CSS stilleri ilişkisel dizi olarak yazılabilir:

$el = Html::el('input');
$el->style['color'] = 'green';
$el->style['display'] = 'block';
echo $el; // '<input style="color:green;display:block">'

Şimdiye kadar özellikleri kullandık, ama aynı sonuca metotlarla da ulaşılabilir:

$el = Html::el('input');
$el->style('color', 'green');
$el->style('display', 'block');
echo $el; // '<input style="color:green;display:block">'

Ya da en ayrıntılı biçimde:

$el = Html::el('input');
$el->appendAttribute('style', 'color', 'green');
$el->appendAttribute('style', 'display', 'block');
echo $el; // '<input style="color:green;display:block">'

Son bir ayrıntı: href() metodu, URL sorgu parametrelerini oluşturmayı kolaylaştırabilir:

echo Html::el('a')->href('index.php', [
	'id' => 10,
	'lang' => 'en',
]);
// '<a href="index.php?id=10&amp;lang=en"></a>'

Data Nitelikleri

Data niteliklerinin özel bir desteği vardır. Adları tire içerdiğinden özellikler ve metotlar üzerinden erişmek pek şık olmaz; bu yüzden ayrı bir data() metodu vardır:

$el = Html::el('input');
$el->{'data-max-size'} = '500x300'; // pek şık değil
$el->data('max-size', '500x300'); // şık olan bu
echo $el; // '<input data-max-size="500x300">'

Bir data niteliğinin değeri diziyse, otomatik olarak JSON'a serileştirilir:

$el = Html::el('input');
$el->data('items', [1,2,3]);
echo $el; // '<input data-items="[1,2,3]">'

Eleman İçeriği

Elemanın iç içeriği setHtml() ya da setText() metotlarıyla ayarlanır. Birincisini yalnızca parametrenin güvenilir biçimde güvenli bir HTML dizesi içerdiğinden eminseniz kullanın.

echo Html::el('span')->setHtml('hello<br>');
// '<span>hello<br></span>'

echo Html::el('span')->setText('10 < 20');
// '<span>10 &lt; 20</span>'

Tersine, iç içerik getHtml() ya da getText() metotlarıyla alınabilir. İkincisi içerikteki HTML etiketlerini kaldırır ve HTML varlıklarını karakterlere geri çevirir.

echo $el->getHtml(); // '10 &lt; 20'
echo $el->getText(); // '10 < 20'

Alt Node'lar

Bir elemanın iç içeriği alt node'lardan oluşan bir dizi de olabilir. Her alt öğe ya bir dize ya da başka bir Html nesnesidir. addHtml() ya da addText() ile eklenirler:

$el = Html::el('span')
	->addHtml('hello<br>')
	->addText('10 < 20')
	->addHtml( Html::el('br') );
// <span>hello<br>10 &lt; 20<br></span>

add() metodu birden çok alt öğeyi tek seferde ekler. Dizeler addText()'teki gibi kaçışlanır, Html nesneleri olduğu gibi eklenir, null değerler atlanır; bu da koşullu içerik için kullanışlıdır. Güvenilir biçimde güvenli HTML olan bir dizeyi Html::html() ile sarın:

$el = Html::el('span')->add(
	'10 < 20',
	Html::el('br'),
	Html::html('hello<br>'),
	$showNote ? Html::el('small')->setText('note') : null,
);
// <span>10 &lt; 20<br>hello<br><small>note</small></span>

Yeni bir Html node'u oluşturup eklemenin başka bir yolu:

$ul = Html::el('ul');
$ul->create('li', ['class' => 'first'])
	->setText('first');
// <ul><li class="first">first</li></ul>

Node'larla dizi öğeleriymiş gibi çalışabilirsiniz. Yani tek tek node'lara köşeli parantezlerle erişebilir, count() ile sayabilir ve üzerlerinde yineleme yapabilirsiniz:

$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

Yeni bir node, insert(?int $index, $child, bool $replace = false) ile belirli bir konuma eklenebilir. $replace = false ise elemanı $index konumuna ekler ve diğerlerini kaydırır. $index = null ise elemanı sona ekler.

// elemanı ilk konuma ekler ve diğerlerini kaydırır
$el->insert(0, Html::el('span'));

Tüm node'lar getChildren() metoduyla alınabilir, removeChildren() metoduyla kaldırılabilir.

Belge Parçası Oluşturma

Bir node kümesiyle çalışmak istiyor ama sarmalayan bir eleman istemiyorsanız, bir belge parçası oluşturabilirsiniz. Yalnızca alt öğelerini render eder, kendine ait bir etiket üretmez. fragment() metodu bunu oluşturur ve tek çağrıda alt öğelerle doldurur; add() ile aynı kuralları izler:

echo Html::fragment(
	Html::el('strong')->setText('hello'),
	'10 < 20',
	Html::el('br'),
);
// <strong>hello</strong>10 &lt; 20<br>

Yalnızca metin ya da yalnızca HTML içeren bir parça, text() ve html() metotlarıyla oluşturulur:

echo Html::text('10 < 20');   // '10 &lt; 20'
echo Html::html('hello<br>'); // 'hello<br>'

4.1.5 öncesi sürümleri desteklemeniz gerekiyorsa, eleman adı yerine null vererek bir parça oluşturun ve addHtml() ile addText() kullanarak doldurun. text() ve html() yerine bu sürümler, hâlâ çalışan ama kullanımdan kaldırılmış olan fromText() ve fromHtml() metotlarını sunar:

$el = Html::el(null)
	->addHtml('hello<br>')
	->addText('10 < 20');
// hello<br>10 &lt; 20

echo Html::fromText('10 < 20');   // '10 &lt; 20'
echo Html::fromHtml('hello<br>'); // 'hello<br>'

HTML Çıktısı Üretme

Bir HTML elemanını çıktılamanın en basit yolu echo kullanmak ya da nesneyi (string) ile dönüştürmektir. Açılış etiketini, kapanış etiketini ve nitelikleri ayrı ayrı da çıktılayabilirsiniz:

$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"'

render(?int $indent = null) metodu düzgün biçimlendirilmiş çıktı sunar. Bir girinti düzeyi verirseniz çıktı birden çok satıra düzgün girintiyle dağıtılır:

echo $el->render(0); // girintili HTML döndürür

Önemli bir özellik de Cross-Site Scripting (XSS) saldırılarına karşı otomatik korumadır. Tüm nitelik değerleri ile setText(), addText(), add() ya da fragment() ile eklenen içerik güvenilir biçimde kaçışlanır:

echo Html::el('div')
	->title('" onmouseover="bad()')
	->setText('<script>bad()</script>');

// <div title='" onmouseover="bad()'>&lt;script&gt;bad()&lt;/script&gt;</div>

HTML ↔ Metin Dönüşümü

HTML'i metne dönüştürmek için statik htmlToText() metodunu kullanabilirsiniz:

echo Html::htmlToText('<span>One &amp; Two</span>'); // 'One & Two'

HtmlStringable

Nette\Utils\Html nesnesi Nette\HtmlStringable arayüzünü uygular. Latte ve Forms bu arayüzü, örneğin HTML kodu döndüren bir __toString() metoduna sahip nesneleri ayırt etmek için kullanır. Böylece nesneyi şablonda {$el} ile yazdırdığınızda çifte kaçışlama olmaz.

versiyon: 4.x