Blade Template Engine

Module 19: PHP Backend - Laravel

Introduction to Blade

Blade is Laravel's powerful, elegant templating engine that combines the familiarity of PHP with enhanced syntax for common tasks. Named after the sharp, efficient anime character, Blade templates are designed to be both powerful and easy to use.

Think of Blade as a specialized tool for crafting your application's user interface - like a high-end 3D printer compared to manually carving objects. It automates repetitive tasks, provides safety features, and allows for modular component design while still giving you complete freedom when needed.

graph TD A[Blade Template] --> B[Blade Compiler] B --> C[Compiled PHP] C --> D[Rendered HTML] E[Template Inheritance] --> A F[Components] --> A G[Directives] --> A

Unlike many templating engines that restrict you from using PHP directly, Blade doesn't limit you. It enhances PHP with convenient shortcuts but allows you to use plain PHP whenever you need to.

Blade Fundamentals

Template Storage and Compilation

Blade templates are stored in the resources/views directory with the .blade.php extension. When a view is requested, Laravel compiles the Blade template into plain PHP and caches it until the template is modified, resulting in virtually zero performance overhead.

This compilation process is similar to how a modern JavaScript bundler works - you write in a more developer-friendly syntax, but the final output is optimized for performance.

Rendering Views


// From a route
Route::get('/welcome', function () {
    return view('welcome', ['name' => 'John']);
});

// From a controller
public function show()
{
    return view('user.profile', ['user' => User::find(1)]);
}
            

The first parameter to the view function corresponds to the name of the Blade template file in the resources/views directory. The second parameter is an array of data to pass to the view.

Note how "dot notation" is used to reference nested directories - user.profile refers to resources/views/user/profile.blade.php.

Basic Syntax

Displaying Data

Blade provides a convenient way to display data passed to your views:


<!-- Display a variable -->
Hello, {{ $name }}

<!-- With default value -->
Welcome, {{ $user->name ?? 'Guest' }}

<!-- Unescaped output (use with caution) -->
{!! $htmlContent !!}
            

The double curly brace syntax {{ }} automatically escapes the output to prevent XSS attacks, similar to how a bank teller places money in a protective envelope before handing it to you - it's a security measure that becomes automatic.

The unescaped output syntax {!! !!} should be used with extreme caution and only with trusted content, as it renders HTML as-is without escaping.

Control Structures

Conditionals


<!-- If statement -->
@if (count($records) === 1)
    I have one record!
@elseif (count($records) > 1)
    I have multiple records!
@else
    I don't have any records!
@endif

<!-- Unless statement (inverse of if) -->
@unless (Auth::check())
    You are not logged in.
@endunless

<!-- Isset check -->
@isset($records)
    // $records is defined and is not null...
@endisset

<!-- Empty check -->
@empty($records)
    // $records is "empty"...
@endempty
            

Loops


<!-- For loop -->
@for ($i = 0; $i < 10; $i++)
    The current value is {{ $i }}
@endfor

<!-- Foreach loop -->
@foreach ($users as $user)
    <p>This is user {{ $user->id }}</p>
@endforeach

<!-- While loop -->
@while (true)
    <p>I'm looping forever.</p>
@endwhile

<!-- Foreach with else -->
@forelse ($users as $user)
    <li>{{ $user->name }}</li>
@empty
    <p>No users found.</p>
@endforelse
            

The @forelse directive is particularly useful - think of it as a smart delivery person who knows exactly what to do if nobody is home. It combines a loop with a built-in empty state handler, eliminating the need for a separate conditional check.

Loop Variable

Within loops, Blade provides a $loop variable with valuable information about the loop's state:


@foreach ($users as $user)
    @if ($loop->first)
        This is the first iteration.
    @endif
    
    @if ($loop->last)
        This is the last iteration.
    @endif
    
    <p>This is user {{ $user->id }} (iteration {{ $loop->iteration }} of {{ $loop->count }})</p>
    
    @if ($loop->even)
        This is an even iteration.
    @endif
    
    @if ($loop->odd)
        This is an odd iteration.
    @endif
@endforeach
            

For nested loops, you can access the parent loop through $loop->parent:


@foreach ($users as $user)
    @foreach ($user->posts as $post)
        @if ($loop->parent->first)
            This is the first iteration of the parent loop.
        @endif
    @endforeach
@endforeach
            

The $loop variable is like having a smart assistant who keeps track of where you are in a process, how far you've come, and how much is left to do.

Including Sub-Views

Blade allows you to include other views within a template, which is excellent for reusable components:

Include Directive


<!-- Include a view -->
@include('shared.errors')

<!-- Include with data -->
@include('view.name', ['status' => 'complete'])
            

Included views inherit all data available to the parent view, but you can also pass additional data as shown above.

Include If/Unless


<!-- Include conditionally -->
@includeIf('view.name', ['some' => 'data'])

<!-- Include when condition is true -->
@includeWhen($boolean, 'view.name', ['some' => 'data'])

<!-- Include when condition is false -->
@includeUnless($boolean, 'view.name', ['some' => 'data'])
            

These conditional includes are like smart building blocks that appear only when needed, making your templates more efficient and adaptable to different situations.

Including First Available View


@includeFirst(['custom.admin', 'admin'], ['some' => 'data'])
            

This will include the first view that exists from the array. It's like having a backup plan - if your preferred option isn't available, you fall back to the next best alternative.

Comments in Blade

Blade provides its own commenting syntax that doesn't appear in the final HTML output:


{{-- This comment will not be present in the rendered HTML --}}
            

This is different from HTML comments (<!-- -->) which are visible in the page source. Blade comments are like stage directions in a play script - they guide the performers but aren't meant to be heard by the audience.

PHP in Blade

You can embed PHP code directly in your Blade templates when needed:


@php
    $counter = 0;
    $fruits = ['apple', 'banana', 'orange'];
@endphp

<p>Counter: {{ $counter }}</p>
            

While Blade provides elegant directives for most common tasks, this escape hatch gives you the flexibility to handle edge cases or complex logic when necessary.

Think of this like a modern car that usually drives itself but still has a steering wheel for when you need manual control.

Raw PHP in Templates

Blade even allows you to use raw PHP tags when needed:


<?php echo 'Hello, World!'; ?>
            

However, using Blade's syntax is generally more concise and readable:


{{ 'Hello, World!' }}
            

The ability to use raw PHP is like having a master key - it's there if you absolutely need it, but you'll rarely want to use it when more elegant solutions exist.

Javascript Frameworks

When working with JavaScript frameworks that also use curly braces (like Vue.js), you may need to indicate that a specific expression should not be processed by Blade:


<!-- This will be processed by Blade -->
{{ $bladeVariable }}

<!-- This will be left untouched for Vue.js -->
@{{ vueVariable }}

<!-- For larger sections -->
@verbatim
    <div>
        Hello, {{ vueVariable }}
    </div>
@endverbatim
            

This is like having a universal translator with a "pass-through" mode that allows certain phrases to remain in their original language without translation.

Real-World Example

Let's look at a practical example of a Blade template for displaying a list of products:


<!-- resources/views/products/index.blade.php -->
<div class="product-grid">
    @forelse ($products as $product)
        <div class="product-card {{ $product->in_stock ? 'in-stock' : 'out-of-stock' }}">
            <h3>{{ $product->name }}</h3>
            
            @if ($product->discount_percent > 0)
                <div class="discount-badge">
                    {{ $product->discount_percent }}% OFF
                </div>
            @endif
            
            <div class="product-price">
                @if ($product->original_price > $product->current_price)
                    <span class="original-price">{{ $product->original_price }}</span>
                @endif
                <span class="current-price">{{ $product->current_price }}</span>
            </div>
            
            <div class="product-actions">
                @if ($product->in_stock)
                    <button class="add-to-cart">Add to Cart</button>
                @else
                    <button class="notify-me">Notify Me</button>
                @endif
                
                @include('products.partials.wishlist-button', ['product' => $product])
            </div>
        </div>
    @empty
        <div class="no-products">
            <p>No products found matching your criteria.</p>
            <a href="{{ route('products.index') }}">View all products</a>
        </div>
    @endforelse
</div>

@if ($products->hasPages())
    <div class="pagination">
        {{ $products->links() }}
    </div>
@endif
            

This example demonstrates several Blade features:

Notice how the template focuses on presentation concerns while the underlying data structure ($products) would be prepared in the controller.

Practice Activity

Basic Blade Template

Create a Blade template for a user profile page that displays:

  1. The user's name, email, and join date
  2. A list of their recent activities with appropriate empty state handling
  3. Conditional content based on user role (admin vs regular user)
  4. Use at least three different Blade directives in your template

Iterating with the Loop Variable

Create a template that displays a table of data using the $loop variable to:

  1. Add a "first" class to the first row
  2. Add a "last" class to the last row
  3. Add "odd" and "even" classes to appropriate rows
  4. Display the iteration count for each row

Conditional Includes

Create three different partial templates and a main template that:

  1. Always includes one partial
  2. Conditionally includes a second partial based on a variable
  3. Uses @includeFirst to include either a custom or default version of the third partial

Summary

In the next lecture, we'll explore Blade directives and control structures in more detail, as well as the powerful template inheritance system.