Daftar tugas, baris tabel, kartu produk — hampir semua halaman web dibangun dari perulangan data. Tidak heran bila @foreach menjadi directive yang paling sering kita tulis di Blade. Larinya pun sederhana: blok di dalam @foreach diulang sekali untuk setiap item, persis foreach PHP. Yang membuat Blade istimewa adalah variabel $loop yang tersedia otomatis di setiap perulangan — tanpa kita menghitung counter manual. Chapter ini menguji @foreach, $loop, @forelse, @for, dan @while dengan output nyata dari setiap skenario.

Perulangan Koleksi dengan @foreach #

Bentuk dasarnya mengambil satu item dari koleksi lalu menampilkannya di dalam blok. Controller mengirim array tugas; view mengulang dan menampilkan tiap judul:

blade
<ul>
@foreach ($tugas as $judul)
    <li>{{ $judul }}</li>
@endforeach
</ul>

Untuk associative array atau model Eloquent, bentuk @foreach ($tugas as $kunci => $nilai) juga tersedia seperti pada PHP biasa. Collection Laravel — hasil Task::all() misalnya — diperlakukan sama persis seperti array, jadi satu directive ini menutup hampir semua kebutuhan perulangan tampilan.

Variabel $loop #

Di dalam @foreach dan @forelse, Blade menyediakan objek $loop yang memuat posisi serta kondisi iterasi berjalan. Propertinya yang paling sering dipakai:

PropertiArti
$loop->indexIndeks iterasi berjalan, mulai dari 0
$loop->iterationNomor iterasi berjalan, mulai dari 1
$loop->remainingJumlah item tersisa setelah iterasi ini
$loop->countTotal item dalam koleksi
$loop->firsttrue bila iterasi pertama
$loop->lasttrue bila iterasi terakhir
$loop->depthKedalaman nested loop, mulai dari 1
$loop->parentObjek $loop dari perulangan induk

View daftar-tugas.blade.php memakai lima properti pertama sekaligus:

blade
<ul>
@foreach ($tugas as $judul)
    <li>{{ $loop->iteration }}. {{ $judul }} — index {{ $loop->index }}, sisa {{ $loop->remaining }}, total {{ $loop->count }}{{ $loop->first ? ' [pertama]' : '' }}{{ $loop->last ? ' [terakhir]' : '' }}</li>
@endforeach
</ul>

Output yang Dihasilkan untuk tiga tugas:

text
<ul>
    <li>1. Belajar Blade — index 0, sisa 2, total 3 [pertama]</li>
    <li>2. Uji coba view — index 1, sisa 1, total 3</li>
    <li>3. Tulis migration — index 2, sisa 0, total 3 [terakhir]</li>
</ul>

Perhatikan pasangan iteration dan index: yang pertama mulai dari 1 untuk nomor urut tampilan, yang kedua mulai dari 0 sesuai kebiasaan indeks PHP. Kedua konvensi ini sering tertukar, padahal keduanya melayani kebutuhan berbeda. Tanpa $loop, kita terpaksa memelihara counter manual seperti @php $i = 1; @endphp lalu menaikkannya di akhir blok — kode yang mudah lupa ditulis dan rawan meleset saat ada @continue di tengah perulangan.

Perulangan Bersarang dan $loop->parent #

Saat satu @foreach berada di dalam @foreach lain, variabel $loop milik perulangan terdalam otomatis menimpa yang luar. Untuk mengakses $loop induk, gunakan $loop->parent. View kategori-tugas.blade.php mengelompokkan tugas per kategori lalu memberi nomor ganda:

blade
@foreach ($kategori as $nama => $daftar)
    <h2>{{ $nama }}</h2>
    <ul>
    @foreach ($daftar as $judul)
        <li>grup {{ $loop->parent->iteration }}. item {{ $loop->iteration }} — {{ $judul }}</li>
    @endforeach
    </ul>
@endforeach

Output yang Dihasilkan:

text
<h2>Rumah Tangga</h2>
    <ul>
            <li>grup 1. item 1 — Cuci baju</li>
            <li>grup 1. item 2 — Beli sayur</li>
        </ul>
    <h2>Belajar</h2>
    <ul>
            <li>grup 2. item 1 — Baca dokumentasi</li>
        </ul>

Nomor grup berasal dari perulangan luar melalui $loop->parent->iteration, sedangkan nomor item dari perulangan dalam. Untuk kedalaman lebih dari dua tingkat, $loop->parent->parent menulusuri ke atas sesuai jumlah tingkatnya.

@forelse untuk Kondisi Kosong #

Masalah klasik @foreach: koleksi kosong menghasilkan elemen pembungkus kosong — tabel tanpa baris, daftar tanpa isi. Directive @forelse memecahnya dengan blok @empty yang hanya dirender saat koleksi kosong:

blade
<table>
    <tr><th>Judul</th><th>Status</th></tr>
    @forelse ($tugas as $t)
        <tr><td>{{ $t['judul'] }}</td><td>{{ $t['status'] }}</td></tr>
    @empty
        <tr><td colspan="2">Tidak ada tugas yang cocok dengan filter.</td></tr>
    @endforelse
</table>

Output untuk koleksi terisi dan koleksi kosong:

text
<table>
    <tr><th>Judul</th><th>Status</th></tr>
            <tr><td>Belajar Blade</td><td>selesai</td></tr>
            <tr><td>Tulis migration</td><td>proses</td></tr>
    </table>

<table>
    <tr><th>Judul</th><th>Status</th></tr>
            <tr><td colspan="2">Tidak ada tugas yang cocok dengan filter.</td></tr>
    </table>

Variabel $loop juga tersedia di dalam @forelse, jadi semua properti pada tabel sebelumnya tetap berlaku.

@for dan @while untuk Perulangan Numerik #

Bila yang diulang bukan koleksi melainkan rentang angka — nomor halaman misalnya — @for lebih tepat:

blade
<nav>
@for ($i = 1; $i <= 3; $i++)
    <a href="?halaman={{ $i }}">H{{ $i }}</a>
@endfor
</nav>

Sementara @while mengulang selama kondisi benar — cocok untuk pagination yang nomornya dihitung dari total data:

blade
@php $halaman = 4; @endphp
<div>
@while ($halaman <= 6)
    <a href="?halaman={{ $halaman }}">H{{ $halaman }}</a>
    @php $halaman++; @endphp
@endwhile
</div>

Output yang Dihasilkan:

text
<nav>
    <a href="?halaman=1">H1</a>
    <a href="?halaman=2">H2</a>
    <a href="?halaman=3">H3</a>
</nav>

<div>
    <a href="?halaman=4">H4</a>
        <a href="?halaman=5">H5</a>
        <a href="?halaman=6">H6</a>
    </div>

Menghentikan dan Melewati Iterasi #

Dua directive khusus mengendalikan perulangan dari dalam. @continue melompati iterasi berjalan, @break menghentikan seluruh perulangan — keduanya menerima kondisi sebagai argumen. View filter-tugas.blade.php melewati judul berstatus draf lalu berhenti setelah dua item:

blade
<ul>
@foreach ($tugas as $judul)
    @continue($judul === 'Draf')
    <li>{{ $judul }}</li>
@endforeach
</ul>

@php $maks = 2; @endphp
<span>Dua item pertama:</span>
@foreach ($tugas as $judul)
    @if ($loop->iteration > $maks)
        @break
    @endif
    <b>{{ $judul }}</b>
@endforeach

Output yang Dihasilkan untuk ['Belajar Blade', 'Draf', 'Uji coba view', 'Tulis migration']:

text
<ul>
        <li>Belajar Blade</li>
            <li>Uji coba view</li>
        <li>Tulis migration</li>
</ul>

<span>Dua item pertama:</span>
        <b>Belajar Blade</b>
        <b>Draf</b>

Item Draf tidak pernah menjadi <li> di daftar pertama, dan daftar kedua berhenti tepat setelah dua item.

Perulangan menuntaskan kosakata dinamis satu halaman. Berikutnya kita angkat kerja yang membuat puluhan halaman konsisten: mewariskan satu layout induk kepada semua halaman anak lewat @extends — materi chapter Template Inheritance.