Nette Documentation Preview

syntax
Tudo o que você sempre quis saber sobre {alfabetizar-assim}
***********************************************************

.[perex]
A etiqueta `{iterateWhile}` é adequada para vários truques em ciclos anteriores.

Suponha que tenhamos a seguinte tabela de banco de dados, onde os itens são divididos em categorias:

| id  |  catId  |  name
|------------------
| 1   |      1  | Apple
| 2   |      1  | Banana
| 3   |      2  | PHP
| 4   |      3  | Green
| 5   |      3  | Red
| 6   |      3  | Blue

Naturalmente, desenhar itens em um laço na frente como uma lista é fácil:

```latte
<ul>
{foreach $items as $item}
	<li>{$item->name}</li>
{/foreach}
</ul>
```

Mas o que fazer se você quiser apresentar cada categoria em uma lista separada? Em outras palavras, como resolver a tarefa de agrupar itens de uma lista linear em um ciclo foreach. A saída deve se parecer com isto:

```latte
<ul>
	<li>Apple</li>
	<li>Banana</li>
</ul>

<ul>
	<li>PHP</li>
</ul>

<ul>
	<li>Green</li>
	<li>Red</li>
	<li>Blue</li>
</ul>
```

Mostraremos a facilidade e a elegância com que a tarefa pode ser resolvida com iteração:

```latte
{foreach $items as $item}
	<ul>
		{iterateWhile}
			<li>{$item->name}</li>
		{/iterateWhile $item->catId === $iterator->nextValue->catId}
	</ul>
{/foreach}
```

Enquanto `{foreach}` marca a parte externa do ciclo, ou seja, o desenho de listas para cada categoria, as tags `{iterateWhile}` indicam a parte interna, ou seja, os itens individuais.
A condição na etiqueta final diz que a repetição continuará enquanto o elemento atual e o próximo elemento pertencerem à mesma categoria (`$iterator->nextValue` é o [próximo item |/tags#$iterator]).

Se a condição for sempre preenchida, então todos os elementos são desenhados no ciclo interno:

```latte
{foreach $items as $item}
	<ul>
		{iterateWhile}
			<li>{$item->name}
		{/iterateWhile true}
	</ul>
{/foreach}
```

O resultado será o seguinte:

```latte
<ul>
	<li>Apple</li>
	<li>Banana</li>
	<li>PHP</li>
	<li>Green</li>
	<li>Red</li>
	<li>Blue</li>
</ul>
```

De que serve tal uso da iteração enquanto? De que forma difere da solução que mostramos logo no início deste tutorial? A diferença é que se a tabela estiver vazia e não contiver nenhum elemento, ela não irá tornar vazia `<ul></ul>`.


Solução Sem `{iterateWhile}` .[#toc-solution-without-iteratewhile]
------------------------------------------------------------------

Se resolvêssemos a mesma tarefa com construções completamente básicas de sistemas de modelos, por exemplo em Twig, Blade ou PHP puro, a solução seria algo parecido com isto:

```latte
{var $prevCatId = null}
{foreach $items as $item}
	{if $item->catId !== $prevCatId}
		{* the category has changed *}

		{* we close the previous <ul>, if it is not the first item *}
		{if $prevCatId !== null}
			</ul>
		{/if}

		{* abriremos uma nova lista *}
		<ul>

		{do $prevCatId = $item->catId}
	{/if}

	<li>{$item->name}</li>
{/foreach}

{if $prevCatId !== null}
	{* we close the last list *}
	</ul>
{/if}
```

No entanto, este código é incompreensível e pouco intuitivo. A conexão entre as tags HTML de abertura e fechamento não é clara em absoluto. Não é clara à primeira vista, se houver um erro. E requer variáveis auxiliares como `$prevCatId`.

Em contraste, a solução com `{iterateWhile}` é limpa, clara, não necessita de variáveis auxiliares e é infalível.


Condição na Etiqueta de Fechamento .[#toc-condition-in-the-closing-tag]
-----------------------------------------------------------------------

Se especificarmos uma condição na etiqueta de abertura `{iterateWhile}`, o comportamento muda: a condição (e o avanço para o próximo elemento) é executada no início do ciclo interno, não no final.
Assim, enquanto `{iterateWhile}` sem condição é sempre inserido, `{iterateWhile $cond}` é inserido somente quando a condição `$cond` é cumprida. Ao mesmo tempo, o seguinte elemento é escrito para `$item`.

Isto é útil, por exemplo, em uma situação em que você quer renderizar o primeiro elemento de cada categoria de uma maneira diferente, como por exemplo:

```latte
<h1>Apple</h1>
<ul>
	<li>Banana</li>
</ul>

<h1>PHP</h1>
<ul>
</ul>

<h1>Green</h1>
<ul>
	<li>Red</li>
	<li>Blue</li>
</ul>
```

Vamos modificar o código original, primeiro desenhamos um item e depois itens adicionais da mesma categoria no laço interno `{iterateWhile}`:

```latte
{foreach $items as $item}
	<h1>{$item->name}</h1>
	<ul>
		{iterateWhile $item->catId === $iterator->nextValue->catId}
			<li>{$item->name}</li>
		{/iterateWhile}
	</ul>
{/foreach}
```


Laços aninhados .[#toc-nested-loops]
------------------------------------

Podemos criar vários loops internos em um ciclo e até mesmo aninhá-los. Desta forma, por exemplo, as subcategorias poderiam ser agrupadas.

Suponha que haja outra coluna na tabela `subCatId` e que, além de cada categoria estar em uma `<ul>`cada subcategoria estará em uma subcategoria separada `<ol>`:

```latte
{foreach $items as $item}
	<ul>
		{iterateWhile}
			<ol>
				{iterateWhile}
					<li>{$item->name}
				{/iterateWhile $item->subCatId === $iterator->nextValue->subCatId}
			</ol>
		{/iterateWhile $item->catId === $iterator->nextValue->catId}
	</ul>
{/foreach}
```


Filtro |batch .[#toc-filter-batch]
----------------------------------

O agrupamento de itens lineares também é fornecido por um filtro `batch`, em lotes com um número fixo de elementos:

```latte
<ul>
{foreach ($items|batch:3) as $batch}
	{foreach $batch as $item}
		<li>{$item->name}</li>
	{/foreach}
{/foreach}
</ul>
```

Ela pode ser substituída por iteração, enquanto que, como se segue:

```latte
<ul>
{foreach $items as $item}
	{iterateWhile}
		<li>{$item->name}</li>
	{/iterateWhile $iterator->counter0 % 3}
{/foreach}
</ul>
```

{{leftbar: /@left-menu}}

Tudo o que você sempre quis saber sobre {alfabetizar-assim}

A etiqueta {iterateWhile} é adequada para vários truques em ciclos anteriores.

Suponha que tenhamos a seguinte tabela de banco de dados, onde os itens são divididos em categorias:

id catId name
1 1 Apple
2 1 Banana
3 2 PHP
4 3 Green
5 3 Red
6 3 Blue

Naturalmente, desenhar itens em um laço na frente como uma lista é fácil:

<ul>
{foreach $items as $item}
	<li>{$item->name}</li>
{/foreach}
</ul>

Mas o que fazer se você quiser apresentar cada categoria em uma lista separada? Em outras palavras, como resolver a tarefa de agrupar itens de uma lista linear em um ciclo foreach. A saída deve se parecer com isto:

<ul>
	<li>Apple</li>
	<li>Banana</li>
</ul>

<ul>
	<li>PHP</li>
</ul>

<ul>
	<li>Green</li>
	<li>Red</li>
	<li>Blue</li>
</ul>

Mostraremos a facilidade e a elegância com que a tarefa pode ser resolvida com iteração:

{foreach $items as $item}
	<ul>
		{iterateWhile}
			<li>{$item->name}</li>
		{/iterateWhile $item->catId === $iterator->nextValue->catId}
	</ul>
{/foreach}

Enquanto {foreach} marca a parte externa do ciclo, ou seja, o desenho de listas para cada categoria, as tags {iterateWhile} indicam a parte interna, ou seja, os itens individuais. A condição na etiqueta final diz que a repetição continuará enquanto o elemento atual e o próximo elemento pertencerem à mesma categoria ($iterator->nextValue é o próximo item).

Se a condição for sempre preenchida, então todos os elementos são desenhados no ciclo interno:

{foreach $items as $item}
	<ul>
		{iterateWhile}
			<li>{$item->name}
		{/iterateWhile true}
	</ul>
{/foreach}

O resultado será o seguinte:

<ul>
	<li>Apple</li>
	<li>Banana</li>
	<li>PHP</li>
	<li>Green</li>
	<li>Red</li>
	<li>Blue</li>
</ul>

De que serve tal uso da iteração enquanto? De que forma difere da solução que mostramos logo no início deste tutorial? A diferença é que se a tabela estiver vazia e não contiver nenhum elemento, ela não irá tornar vazia <ul></ul>.

Solução Sem {iterateWhile}

Se resolvêssemos a mesma tarefa com construções completamente básicas de sistemas de modelos, por exemplo em Twig, Blade ou PHP puro, a solução seria algo parecido com isto:

{var $prevCatId = null}
{foreach $items as $item}
	{if $item->catId !== $prevCatId}
		{* the category has changed *}

		{* we close the previous <ul>, if it is not the first item *}
		{if $prevCatId !== null}
			</ul>
		{/if}

		{* abriremos uma nova lista *}
		<ul>

		{do $prevCatId = $item->catId}
	{/if}

	<li>{$item->name}</li>
{/foreach}

{if $prevCatId !== null}
	{* we close the last list *}
	</ul>
{/if}

No entanto, este código é incompreensível e pouco intuitivo. A conexão entre as tags HTML de abertura e fechamento não é clara em absoluto. Não é clara à primeira vista, se houver um erro. E requer variáveis auxiliares como $prevCatId.

Em contraste, a solução com {iterateWhile} é limpa, clara, não necessita de variáveis auxiliares e é infalível.

Condição na Etiqueta de Fechamento

Se especificarmos uma condição na etiqueta de abertura {iterateWhile}, o comportamento muda: a condição (e o avanço para o próximo elemento) é executada no início do ciclo interno, não no final. Assim, enquanto {iterateWhile} sem condição é sempre inserido, {iterateWhile $cond} é inserido somente quando a condição $cond é cumprida. Ao mesmo tempo, o seguinte elemento é escrito para $item.

Isto é útil, por exemplo, em uma situação em que você quer renderizar o primeiro elemento de cada categoria de uma maneira diferente, como por exemplo:

<h1>Apple</h1>
<ul>
	<li>Banana</li>
</ul>

<h1>PHP</h1>
<ul>
</ul>

<h1>Green</h1>
<ul>
	<li>Red</li>
	<li>Blue</li>
</ul>

Vamos modificar o código original, primeiro desenhamos um item e depois itens adicionais da mesma categoria no laço interno {iterateWhile}:

{foreach $items as $item}
	<h1>{$item->name}</h1>
	<ul>
		{iterateWhile $item->catId === $iterator->nextValue->catId}
			<li>{$item->name}</li>
		{/iterateWhile}
	</ul>
{/foreach}

Laços aninhados

Podemos criar vários loops internos em um ciclo e até mesmo aninhá-los. Desta forma, por exemplo, as subcategorias poderiam ser agrupadas.

Suponha que haja outra coluna na tabela subCatId e que, além de cada categoria estar em uma <ul>cada subcategoria estará em uma subcategoria separada <ol>:

{foreach $items as $item}
	<ul>
		{iterateWhile}
			<ol>
				{iterateWhile}
					<li>{$item->name}
				{/iterateWhile $item->subCatId === $iterator->nextValue->subCatId}
			</ol>
		{/iterateWhile $item->catId === $iterator->nextValue->catId}
	</ul>
{/foreach}

Filtro |batch

O agrupamento de itens lineares também é fornecido por um filtro batch, em lotes com um número fixo de elementos:

<ul>
{foreach ($items|batch:3) as $batch}
	{foreach $batch as $item}
		<li>{$item->name}</li>
	{/foreach}
{/foreach}
</ul>

Ela pode ser substituída por iteração, enquanto que, como se segue:

<ul>
{foreach $items as $item}
	{iterateWhile}
		<li>{$item->name}</li>
	{/iterateWhile $iterator->counter0 % 3}
{/foreach}
</ul>