[2008-12-12] Novinky v curlyBracket­sFilter

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
David Grudl
Nette Core | 8099
+
0
-

V cyklech {foreach ...} ... {/foreach} se automaticky inicializuje proměnná $iterator, která obsahuje čístač a umí zjistit, zda je aktuální prvek první nebo poslední. Příklad použití:

{foreach $rows as $row}
	{if $iterator->isFirst()}
	<table>
	{/if}
	<tr id="row-{$iterator->getCounter()}">
		<td>{$row->name}</td>
		<td>{$row->email}</td>
	</tr>
	{if $iterator->isLast()}
	</table>
	{/if}
{/foreach}

Podporované jsou i zanořené cykly. Nevýhodou je samozřejmě o něco málo vyšší režie a blokování proměnné $iterator pro vlastní použití.


Syntax by pak šlo rozšířit o {foreachelse}, tj. oblast pro případ, kdy iterator neobsahuje žádné prvky:

{foreach $rows as $row}
	...
{foreachelse}
	<p>V tabulce nejsou žádné záznamy</p>
{/foreach}

Druhou novinkou je kontextové připínání escapování. V HTML by se escapovalo klasicky přes htmlSpecialChars(), v JavaScriptu by se volalo nejspíš json_encode(), pro CSS bych připravil speciální funkci (důvody viz třeba https://phpfashion.com/…-javascriptu). Příklad:

<p>Hodnota: {$value}</p> // ekvivalent <?= htmlSpecialChars($value) ?>
<script>
var value = {$value}; // ekvivalent <?= json_encode($value) ?>
</script>

A do třetice: díky refactoringu uvažuju nad přesunutím podpory pro snippety ze třídy Control přímo do šablon. Takže se ptám, jestli někdo přímo nepoužívá metody $control->beginSnippet() a $control->endSnippet()?

Honza Marek
Člen | 1664
+
0
-

{foreachelse} vypadá na první pohled hezky… ale asi by se to muselo používat s tím {if $iterator->isFirst()}<table>{/if}, což mi nepřijde hezčí než vypsat <table> před {foreach}…

K iterátoru by bylo možná hezké mít metody isOdd a isEven, ale já bych je stejně nepoužil, protože řádky tabulky se dají obarvit přes jQuery :-D

Tomik
Nette Evangelist | 485
+
0
-

Honza M. napsal(a):

{foreachelse} vypadá na první pohled hezky… ale asi by se to muselo používat s tím {if $iterator->isFirst()}<table>{/if}, což mi nepřijde hezčí než vypsat <table> před {foreach}…

K iterátoru by bylo možná hezké mít metody isOdd a isEven, ale já bych je stejně nepoužil, protože řádky tabulky se dají obarvit přes jQuery :-D

No jo, ale v tom případě si musíš někde inicializovat boolean, zda v poli $rows je alespoň jeden záznam, pokud ne, pak vypsat hlášku, že nic není, pokud ano, pak vypsat hlavičku tabulky, tzn. přijde mi to Davidem navrhované řešení lepší (a pokud se to dobře popíše do dokumentace, myslím, že by to ani nemělo mást nové uživatele).

phx
Člen | 651
+
0
-

Tak jako tak jde pouzit novy a stazy zpusob. Table ve foreach nebo pred a za. Toto me vubec netrapi:)

Urcite se ale primlouvam za isOdd a isEven. Jinak pekny.

Dale me jeste napda, ze by se mohlo hodit aby iterator mel nejake citace. Napr kdyz pod tabulkou budu chtit vypsat sumu. I kdyz asi by to bylo jako jit na komara s brokovnici.

Tomik
Nette Evangelist | 485
+
0
-

phx napsal(a):

Tak jako tak jde pouzit novy a stazy zpusob. Table ve foreach nebo pred a za. Toto me vubec netrapi:)

Urcite se ale primlouvam za isOdd a isEven. Jinak pekny.

Dale me jeste napda, ze by se mohlo hodit aby iterator mel nejake citace. Napr kdyz pod tabulkou budu chtit vypsat sumu. I kdyz asi by to bylo jako jit na komara s brokovnici.

Souhlasím s tím, že je to pěkná myšlenka, jinak se také přimlouvám za isOdd a isEven, rozhodně to může ušetřit práci. ;)

David Grudl
Nette Core | 8099
+
0
-

Tomik napsal(a):

Honza M. napsal(a):

{foreachelse} vypadá na první pohled hezky… ale asi by se to muselo používat s tím {if $iterator->isFirst()}<table>{/if}, což mi nepřijde hezčí než vypsat <table> před {foreach}…

No jo, ale v tom případě si musíš někde inicializovat boolean, zda v poli $rows je alespoň jeden záznam, pokud ne, pak vypsat hlášku, že nic není…

Souhlasím, že přínos konstrukce {foreachelse} je sporný.

Jinak isOdd() tam taky je. Jako největší přínost vidím hlavně isLast() – to se jen velmi těžko řeší v běžných podmínkách.

phx
Člen | 651
+
0
-

Na foreachelse bych se asi vykaslal. Zbytecne by jsme tvorili neco co jde vytvorit za pomoci if a navic si myslim, ze s if to bude prehlednejsi.

Honza Marek
Člen | 1664
+
0
-

Snažím se vymyslet nějakou krásnou syntax pro ulehčení napsání toho, že nemám co vypsat. Zatím jsem vymyslel toto. Zhodnocení toho, jestli je to blbost nechám na vás.

{iterate}
	<table>
	{foreach $rows as $row}
		<td>{$row->name}</td>
		<td>...</td>
	{/foreach}
	</table>
{/iterate}

{ifEmpty}
	Nic nemáme
{/ifEmpty}

EDIT: asi je to blbost

{if count($rows) > 0}
	<table>
	{foreach $rows as $row}
		...
	{/foreach}
	</table>
{else}
	Nic tu není
{/if}

Oproti tomuto to rozhodně neni lepší…

Editoval Honza M. (11. 12. 2008 22:33)

Honza Marek
Člen | 1664
+
0
-

A pokud tam bude isOdd, dal bych tam i isEven. Nikdo si nebude pamatovat, kterej z nich tam je…

simon
Člen | 98
+
0
-

nahodou ten iterator je super. ted by se hodil
{foreach $labels as $item}
<a href=„search/tag/{$item[‚bt_name‘]}“>{$item[‚bt_name‘]}</a>,
{/foreach}
vypis stitku ale za poslednim nechci mit carku.

phx
Člen | 651
+
0
-

Ja tohle resil zatim vzdy takto:

$isFirst = true;
foreach($data as $one) {
	if(!$isFirst) echo ', ';
	echo '...';
	$isFirst = false;
}
Patrik Votoček
Člen | 2221
+
0
-

Já dřív u svého frameworku (který sem používal než vyšlo nette) měl něco takového:

<?php
{ifforeach $data}
<ul>
{foreach $data as $value}
<li>{$value}</li>
{/foreach}
</ul>
{elseforeach}
<p>No repeating data</p>
{/ifforeach}
?>

Také uvnitř foreach existoval objekt iterator který vracel zda je to první/poslední/sudý/lichý/kolikátý cikl.

Tomik
Nette Evangelist | 485
+
0
-

Já tedy osobně bych pro {foreachelse} byl, podle mě to zas tak hrozně syntaxi neznepřehledňuje a ten, kdo to nezná, může klidně bez závady (pouze si přidělá práci) používat nějaký vlastní způsob (toto platí i pro ty, kteří to nechtějí). :)

Honza Marek
Člen | 1664
+
0
-

Tomik napsal(a):

Já tedy osobně bych pro {foreachelse} byl, podle mě to zas tak hrozně syntaxi neznepřehledňuje a ten, kdo to nezná, může klidně bez závady (pouze si přidělá práci) používat nějaký vlastní způsob (toto platí i pro ty, kteří to nechtějí). :)

Mohl bys mi předvést příklad, kdy by se {foreachelse} vyplatilo? Přemýšlel jsem o tom, a člověk stejně vždycky nějaký ten výpis potřebuje obalit buď <table></table> nebo <ul></ul>…

David Grudl
Nette Core | 8099
+
0
-

Všechno (kromě foreachelse) je implementované a mělo by to být funkční.

David Grudl
Nette Core | 8099
+
0
-

Protože filtr curlyBrackets narostl, tak jsem jej přesunul do samostatné třídy CurlyBracketsFilter.

// misto $template->registerFilter(/*Nette\Templates\*/'TemplateFilters::curlyBrackets');
$template->registerFilter(/*Nette\Templates\*/'CurlyBracketsFilter::invoke');

Starý způsob funguje, ale vygeneruje varování.

Ola
Člen | 385
+
0
-

Zdravím, po aktualizaci na poslední revizi mi nikde nefungují foreachy .. vždy mi to vyhodí toto:

Parse error: syntax error, unexpected T_AS in C:\www\nette\app\temp\cache-Nette.Template%00ad5a9a3fd70273d0c56f2056ea09836d.LastArticlesControl.phtml on line 10

Na danym řádku je v cache toto:

<?php foreach ($iterator = $_cb->iterators[] = new SmartCachingIterator($posts AS $key => $post"): ?>

EDIT: Tak to je tim, že v templatách píšu AS velkym písmem, ale nahrazuje se jen malý as .. Davide, opravíš to?

Editoval Ola (12. 12. 2008 6:56)

David Grudl
Nette Core | 8099
+
0
-

Je to tím, pošlu opravu.