iterateWhile} Hakkında Her Zaman Bilmek İstediğiniz Her Şey
{iterateWhile}
etiketi foreach döngülerinde çeşitli hileler için uygundur.
Öğelerin kategorilere ayrıldığı aşağıdaki veritabanı tablosuna sahip olduğumuzu varsayalım:
id | catId | name |
---|---|---|
1 | 1 | Apple |
2 | 1 | Banana |
3 | 2 | PHP |
4 | 3 | Green |
5 | 3 | Red |
6 | 3 | Blue |
Elbette, bir foreach döngüsündeki öğeleri liste olarak çizmek kolaydır:
<ul>
{foreach $items as $item}
<li>{$item->name}</li>
{/foreach}
</ul>
Ancak her kategoriyi ayrı bir listede işlemek istiyorsanız ne yapmalısınız? Başka bir deyişle, doğrusal bir listedeki öğeleri bir foreach döngüsü içinde gruplama görevi nasıl çözülür? Çıktı şöyle görünmelidir:
<ul>
<li>Apple</li>
<li>Banana</li>
</ul>
<ul>
<li>PHP</li>
</ul>
<ul>
<li>Green</li>
<li>Red</li>
<li>Blue</li>
</ul>
iterateWhile ile bu görevin ne kadar kolay ve zarif bir şekilde çözülebileceğini göstereceğiz:
{foreach $items as $item}
<ul>
{iterateWhile}
<li>{$item->name}</li>
{/iterateWhile $item->catId === $iterator->nextValue->catId}
</ul>
{/foreach}
{foreach}
döngünün dış kısmını, yani her kategori için listelerin çizilmesini işaret ederken,
{iterateWhile}
etiketleri iç kısmı, yani tek tek öğeleri gösterir. Bitiş etiketindeki koşul, mevcut ve bir
sonraki öğe aynı kategoriye ait olduğu sürece tekrarın devam edeceğini söyler
($iterator->nextValue
bir sonraki öğedir).
Koşul her zaman karşılanırsa, tüm öğeler iç döngüde çizilir:
{foreach $items as $item}
<ul>
{iterateWhile}
<li>{$item->name}
{/iterateWhile true}
</ul>
{/foreach}
Sonuç şu şekilde görünecektir:
<ul>
<li>Apple</li>
<li>Banana</li>
<li>PHP</li>
<li>Green</li>
<li>Red</li>
<li>Blue</li>
</ul>
iterateWhile'ın böyle bir kullanımı ne işe yarar? Bu eğitimin en başında gösterdiğimiz çözümden ne farkı var?
Aradaki fark, tablo boşsa ve herhangi bir öğe içermiyorsa, boş olarak işlenmeyecektir
<ul></ul>
.
{iterateWhile}
Olmadan Çözüm
Aynı görevi şablon sistemlerinin tamamen temel yapılarıyla, örneğin Twig, Blade veya saf PHP ile çözmüş olsaydık, çözüm şuna benzer bir şey olurdu:
{var $prevCatId = null}
{foreach $items as $item}
{if $item->catId !== $prevCatId}
{* kategori değişti *}
{* <ul> ilk öğe değilse</ul>bir öncekini kapatıyoruz <ul>*}
{if $prevCatId !== null}
</ul>
{/if}
{* we will open a new list *}
<ul>
{do $prevCatId = $item->catId}
{/if}
<li>{$item->name}</li>
{/foreach}
{if $prevCatId !== null}
{* we close the last list *}
</ul>
{/if}
Ancak, bu kod anlaşılmaz ve sezgisel değildir. Açılış ve kapanış HTML etiketleri arasındaki bağlantı hiç açık
değildir. Bir hata olup olmadığı ilk bakışta anlaşılmıyor. Ve $prevCatId
gibi yardımcı değişkenler
gerektirir.
Buna karşılık, {iterateWhile}
ile çözüm temiz, net, yardımcı değişkenlere ihtiyaç duymaz ve
hatasızdır.
Kapanış Etiketindeki Koşul
Açılış etiketinde bir koşul belirtirsek {iterateWhile}
, davranış değişir: koşul (ve bir sonraki öğeye
ilerleme) iç döngünün sonunda değil başında yürütülür. Böylece, koşul olmadan {iterateWhile}
her zaman
girilirken, {iterateWhile $cond}
yalnızca $cond
koşulu karşılandığında girilir. Aynı zamanda,
aşağıdaki eleman $item
adresine yazılır.
Bu, örneğin, her kategorideki ilk öğeyi farklı bir şekilde oluşturmak istediğiniz bir durumda kullanışlıdır:
<h1>Apple</h1>
<ul>
<li>Banana</li>
</ul>
<h1>PHP</h1>
<ul>
</ul>
<h1>Green</h1>
<ul>
<li>Red</li>
<li>Blue</li>
</ul>
Orijinal kodu değiştirelim, {iterateWhile}
iç döngüsünde ilk öğeyi ve ardından aynı kategoriden ek
öğeleri çizelim:
{foreach $items as $item}
<h1>{$item->name}</h1>
<ul>
{iterateWhile $item->catId === $iterator->nextValue->catId}
<li>{$item->name}</li>
{/iterateWhile}
</ul>
{/foreach}
İç İçe Döngüler
Bir döngüde birden fazla iç döngü oluşturabilir ve hatta bunları iç içe yerleştirebiliriz. Bu şekilde, örneğin alt kategoriler gruplandırılabilir.
Tabloda başka bir sütun olduğunu varsayalım subCatId
ve her kategorinin ayrı bir kategoride olmasına ek
olarak <ul>
her bir alt kategori ayrı bir <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}
Filtre | yığın
Doğrusal öğelerin gruplandırılması da bir filtre tarafından sağlanır batch
, sabit sayıda öğeye sahip
gruplar halinde:
<ul>
{foreach ($items|batch:3) as $batch}
{foreach $batch as $item}
<li>{$item->name}</li>
{/foreach}
{/foreach}
</ul>
Aşağıdaki gibi iterateWhile ile değiştirilebilir:
<ul>
{foreach $items as $item}
{iterateWhile}
<li>{$item->name}</li>
{/iterateWhile $iterator->counter0 % 3}
{/foreach}
</ul>