When it comes to looping through data in your View
files using Laravel's Blade templates, there is more than one way to skin a cat.
Say you have an array (or some records from your database) that you want to loop through and display in your view file:
$books = [
[
'id' => 1,
'title' => 'Tame of Groans',
'author' => 'George M'
],
[
'id' => 2,
'title' => 'Rort of the Lings',
'author' => 'John T'
],
[
'id' => 3,
'title' => 'Yvan Eht Nioj',
'author' => 'Bart S'
],
];
In app/views/books/index.blade.php
, you have:
@if (count($books))
@foreach($books as $book)
@include('books.single', $book)
@endforeach
@else
<p>No Books exist.</p>
@endif
In app/views/books/single.blade.php
, you have:
<li>{{{ $book['title'] }}} by <strong>{{{ $book['author'] }}}</strong></li>
This will display the $books
array like this:
- Tame of Groans by George M
- Rort of the Lings by John T
- Yvan Eht Nioj by Bart S
If the array is empty, it will simply display No Books exist.
Laravel makes it easier to check for empty data with the forelse
Blade syntax. Amend the above control structure to this:
@forelse($books as $book)
@include('books.single', $book)
@empty
<p>No Books exist.</p>
@endforelse
You will get the exact same results.
I recently came across an undocumented Laravel Blade syntax - each
. It actually simplifies the above example further and makes your code cleaner:
@each('books.single', $books, 'book', 'raw|<p>No Books exist.<p>')
That's it. Again, you will get the exact same results.
This implements the renderEach
method in the Illuminate\View\Factory
class.
public function renderEach($view, $data, $iterator, $empty = 'raw|')
{
...
}
It accepts the View
file and the array as the first two arguments.
The third argument is the variable with the iterated value. Think of it as passing compact('book')
to books.single
after each iteration.
The last parameter displays a View
file or a string if the array is empty. It needs to be prefixed with raw|
if you pass a string as the argument.
In the example above, you could put <p>No Books exist.</p>
into a file apps/views/books/empty.blade.php
. Then change each
to this:
@each('books.single', $books, 'book', 'books.empty')
Exact same results again. High five!