Looping through data with Laravel Blade

Posted on 29 September 2014

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!