🏠 Home / Hub

Laravel 03 — Blade Templates

Blade is Laravel's powerful, lightweight templating engine. Files end in .blade.php and live in resources/views/.

1. Blade Introduction

Blade templates compile to plain PHP and are cached — no performance overhead. Unlike basic PHP, Blade escapes output by default which prevents XSS attacks.

// Return a view from a route or controller
return view('welcome');                          // resources/views/welcome.blade.php
return view('posts.index', ['posts' => $posts]); // resources/views/posts/index.blade.php
return view('posts.show', compact('post'));       // compact() shorthand
SyntaxCompiles ToNote
{{ $var }}<?= e($var) ?>HTML-escaped (safe)
{!! $var !!}<?= $var ?>Raw output (unsafe for user data)
{{-- comment --}}nothingNot rendered in HTML source
@{{ literal }}{{ literal }}Escaped for Vue/Angular use

2. Variable Output & Escaping

<!-- Safe: HTML entities are escaped -->
<h1>{{ $post->title }}</h1>
<p>Author: {{ $post->user->name }}</p>

<!-- Default value if variable is null -->
<p>{{ $name ?? 'Guest' }}</p>

<!-- Raw HTML output — ONLY use for trusted data -->
<div>{!! $post->body_html !!}</div>

<!-- Blade comment (not visible in page source) -->
{{-- Pagination section: render links below the list --}}
{{ $posts->links() }}

<!-- Prevent Blade from processing (for Vue.js etc.) -->
<span>@{{ vueVariable }}</span>
Always use {{ }} for user-generated content. Only use {!! !!} for HTML you generate yourself (e.g., a Markdown parser output).

3. Control Flow Directives

@if / @elseif / @else / @endif

@if ($user->isAdmin())
    <span class="badge">Admin</span>
@elseif ($user->isModerator())
    <span class="badge">Moderator</span>
@else
    <span>Member</span>
@endif

@unless — opposite of @if

@unless (Auth::check())
    <a href="/login">Please log in</a>
@endunless

@isset and @empty

@isset($post->image)
    <img src="{{ $post->image }}" alt="Post image">
@endisset

@empty($posts)
    <p>No posts yet.</p>
@endempty

@if(isset($error))
    <p class="error">{{ $error }}</p>
@endif

4. Loops & the $loop Variable

@foreach

@foreach ($posts as $post)
    <div>
        <h3>{{ $loop->iteration }}. {{ $post->title }}</h3>
        @if ($loop->first) <span>(Newest)</span> @endif
        @if ($loop->last)  <span>(Oldest)</span> @endif
    </div>
@endforeach

@forelse — foreach with empty fallback

@forelse ($posts as $post)
    <p>{{ $post->title }}</p>
@empty
    <p>No posts found.</p>
@endforelse

@for and @while

@for ($i = 1; $i <= 5; $i++)
    <p>Item {{ $i }}</p>
@endfor

@while ($condition)
    <p>Looping...</p>
@endwhile

$loop Variable Properties

PropertyDescription
$loop->indexZero-based iteration index
$loop->iterationOne-based iteration number
$loop->remainingItems remaining in loop
$loop->countTotal items in collection
$loop->firstTrue on first iteration
$loop->lastTrue on last iteration
$loop->even / oddTrue on even/odd iterations
$loop->depthNesting level of current loop
$loop->parentParent loop's $loop in nested loops

5. Template Inheritance

layouts/app.blade.php — the master layout

<!DOCTYPE html>
<html>
<head>
    <title>@yield('title', 'My App')</title>
    @stack('styles')
</head>
<body>
    <nav>...navigation...</nav>

    <main>
        @yield('content')
    </main>

    <footer>@yield('footer', '&copy; 2024')</footer>
    @stack('scripts')
</body>
</html>

posts/index.blade.php — child view

@extends('layouts.app')

@section('title', 'All Posts')

@section('content')
    <h1>Posts</h1>
    @forelse($posts as $post)
        <p>{{ $post->title }}</p>
    @empty
        <p>No posts.</p>
    @endforelse
@endsection

@push('scripts')
    <script src="/js/posts.js"></script>
@endpush

@include — embed a partial view

@include('partials.navbar')
@include('partials.alert', ['type' => 'success', 'msg' => 'Saved!'])

@includeIf('partials.sidebar')              // only if file exists
@includeWhen($user->isAdmin(), 'admin.bar') // conditional

6. Blade Components

Anonymous Component (no PHP class needed)

<!-- resources/views/components/alert.blade.php -->
<div class="alert alert-{{ $type }}">
    <strong>{{ $title }}</strong>
    {{ $slot }}
</div>
<!-- Use the component with x- prefix -->
<x-alert type="success" title="Done!">
    Your post has been saved.
</x-alert>

Class-based Component

php artisan make:component Alert
# Creates: app/View/Components/Alert.php
#          resources/views/components/alert.blade.php
// app/View/Components/Alert.php
class Alert extends Component
{
    public function __construct(
        public string $type = 'info',
        public string $title = ''
    ) {}

    public function render()
    {
        return view('components.alert');
    }
}

7. CSRF Protection with @csrf

Every HTML form that submits to a POST/PUT/PATCH/DELETE route must include the CSRF token. Without it, Laravel returns a 419 error.

<form method="POST" action="/posts">
    @csrf
    <!-- Renders a hidden input with the CSRF token -->
    <!-- <input type="hidden" name="_token" value="abc123..."> -->

    <input name="title" type="text">
    <button type="submit">Save</button>
</form>

For PUT/PATCH/DELETE — HTML forms only support GET and POST, so use method spoofing:

<form method="POST" action="/posts/{{ $post->id }}">
    @csrf
    @method('PUT')   <!-- Adds <input name="_method" value="PUT"> -->
    ...
</form>

<!-- DELETE example -->
<form method="POST" action="/posts/{{ $post->id }}">
    @csrf
    @method('DELETE')
    <button>Delete Post</button>
</form>
CSRF stands for Cross-Site Request Forgery. The token verifies that form submissions originate from your own application, not a malicious third-party site.

8. Stack Directives — @push / @stack

Stacks let child views inject CSS or JS into specific sections of a layout without modifying the layout file.

<!-- In layout (head section) -->
@stack('styles')

<!-- In layout (before </body>) -->
@stack('scripts')

<!-- In child view — push CSS -->
@push('styles')
    <link rel="stylesheet" href="/css/editor.css">
@endpush

<!-- In child view — push JS -->
@push('scripts')
    <script src="/js/editor.js"></script>
    <script>initEditor();</script>
@endpush

<!-- @prepend — push to beginning of stack -->
@prepend('scripts')
    <script src="/js/polyfill.js"></script>
@endprepend

9. Raw PHP in Blade

@php
    $total = 0;
    foreach ($items as $item) {
        $total += $item->price;
    }
    $tax = $total * 0.15;
@endphp

<p>Subtotal: ${{ number_format($total, 2) }}</p>
<p>Tax (15%): ${{ number_format($tax, 2) }}</p>
<p>Total: ${{ number_format($total + $tax, 2) }}</p>
Keep @php blocks minimal — move complex logic to controllers, view composers, or helper classes instead.

10. Blade Directives Reference

DirectivePurpose
@extends('layout')Inherit from a parent layout
@section('name') ... @endsectionDefine a named section
@yield('name')Output a section in layout
@parentInclude parent section content
@include('view')Include a partial view
@if / @elseif / @else / @endifConditional rendering
@unless ... @endunlessInverse of @if
@isset / @endissetCheck variable is set
@empty / @endemptyCheck variable is empty
@foreach / @endforeachLoop over collection
@forelse / @empty / @endforelseLoop with empty fallback
@for / @endforC-style for loop
@while / @endwhileWhile loop
@break / @continueLoop flow control
@csrfCSRF hidden token field
@method('PUT')HTTP method spoofing
@auth / @endauthShow if authenticated
@guest / @endguestShow if not authenticated
@can('action', $model)Show if user has permission
@push / @endpushPush content to a stack
@stack('name')Output a stack in layout
@php ... @endphpRaw PHP block
@dump($var)Debug dump a variable
@dd($var)Dump and die

📌 Study Checklist