Blade Templating Engine
Blade is Laravel's powerful templating engine that provides an elegant syntax for working with views. Unlike other PHP templating engines, Blade doesn't re
Blade is Laravel's powerful templating engine that provides an elegant syntax for working with views. Unlike other PHP templating engines, Blade doesn't restrict you from using plain PHP code in views. Blade view files use the .blade.php extension and are stored in the resources/views directory.
Advantages:
The most basic task is displaying data passed to views using double curly braces:
1{{-- Escaped output (safe) --}}
2<h1>{{ $title }}</h1>
3<p>{{ $user->name }}</p>
4
5{{-- Raw output (dangerous - use with caution) --}}
6<div>{!! $htmlContent !!}</div>
7
8{{-- Display with default value --}}
9<p>{{ $name ?? 'Guest' }}</p>
10
11{{-- Call PHP functions --}}
12<p>{{ strtoupper($title) }}</p>
13<p>{{ date('Y-m-d') }}</p>1{{-- This is a Blade comment --}}
2{{-- It won't be rendered in HTML --}}
3
4{{--
5 Multi-line Blade comment
6 Useful for documentation
7--}}When you need to display curly braces without Blade processing them:
1@verbatim
2 <div>
3 {{ This will not be processed by Blade }}
4 {{ Useful for Vue.js, Alpine.js templates }}
5 </div>
6@endverbatimIf Statements:
1@if ($user->isAdmin())
2 <p>Welcome, Administrator!</p>
3@elseif ($user->isModerator())
4 <p>Welcome, Moderator!</p>
5@else
6 <p>Welcome, User!</p>
7@endif
8
9{{-- Unless directive (opposite of if) --}}
10@unless ($user->isGuest())
11 <p>You are logged in.</p>
12@endunless
13
14{{-- Authenticated check --}}
15@auth
16 <p>You are logged in as {{ auth()->user()->name }}</p>
17@endauth
18
19@guest
20 <p>Please <a href="/login">log in</a></p>
21@endguest
22
23{{-- Check specific guard --}}
24@auth('admin')
25 <p>Admin logged in</p>
26@endauthIsset and Empty:
1@isset($records)
2 <p>Records variable is set</p>
3@endisset
4
5@empty($records)
6 <p>No records found</p>
7@endemptyEnvironment Checks:
1@production
2 {{-- Production-only code --}}
3 <script src="{{ asset('js/analytics.js') }}"></script>
4@endproduction
5
6@env('local')
7 {{-- Local environment code --}}
8 <div class="debug-toolbar"></div>
9@endenv
10
11@env(['staging', 'production'])
12 {{-- Multiple environments --}}
13@endenvForeach Loop:
1@foreach ($users as $user)
2 <div class="user">
3 <h3>{{ $user->name }}</h3>
4 <p>{{ $user->email }}</p>
5 </div>
6@endforeach
7
8{{-- With else for empty arrays --}}
9@forelse ($posts as $post)
10 <article>
11 <h2>{{ $post->title }}</h2>
12 <p>{{ $post->excerpt }}</p>
13 </article>
14@empty
15 <p>No posts available.</p>
16@endforelseFor Loop:
1@for ($i = 0; $i < 10; $i++)
2 <p>Iteration {{ $i }}</p>
3@endforWhile Loop:
1@while ($count < 100)
2 <p>Count: {{ $count }}</p>
3 @php $count++; @endphp
4@endwhileLoop Variable:
Blade provides a $loop variable inside loops:
1@foreach ($users as $user)
2 <div class="user @if($loop->first) first @endif @if($loop->last) last @endif">
3 <p>User {{ $loop->iteration }} of {{ $loop->count }}</p>
4 <p>{{ $user->name }}</p>
5
6 @if (!$loop->last)
7 <hr>
8 @endif
9 </div>
10@endforeachLoop Properties:
$loop->index: Current iteration (starts at 0)$loop->iteration: Current iteration (starts at 1)$loop->remaining: Iterations remaining$loop->count: Total items$loop->first: First iteration$loop->last: Last iteration$loop->even: Even iteration$loop->odd: Odd iteration$loop->depth: Nesting level$loop->parent: Parent loop variable (in nested loops)**Main Layout (resources/views/layouts/app.blade.php):**
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <meta name="csrf-token" content="{{ csrf_token() }}">
7
8 <title>@yield('title', 'Default Title')</title>
9
10 {{-- Styles stack --}}
11 @stack('styles')
12
13 <link rel="stylesheet" href="{{ asset('css/app.css') }}">
14</head>
15<body>
16 {{-- Header section --}}
17 @include('partials.header')
18
19 {{-- Main content --}}
20 <main class="container">
21 @yield('content')
22 </main>
23
24 {{-- Footer section --}}
25 @include('partials.footer')
26
27 {{-- Scripts --}}
28 <script src="{{ asset('js/app.js') }}"></script>
29
30 @stack('scripts')
31</body>
32</html>**Child View (resources/views/posts/show.blade.php):**
1@extends('layouts.app')
2
3@section('title', 'View Post')
4
5@push('styles')
6 <link rel="stylesheet" href="{{ asset('css/posts.css') }}">
7@endpush
8
9@section('content')
10 <article class="post">
11 <h1>{{ $post->title }}</h1>
12
13 <div class="meta">
14 <span>By {{ $post->author->name }}</span>
15 <span>{{ $post->created_at->format('M d, Y') }}</span>
16 </div>
17
18 <div class="content">
19 {!! $post->content !!}
20 </div>
21
22 @if ($post->tags->count())
23 <div class="tags">
24 @foreach ($post->tags as $tag)
25 <span class="tag">{{ $tag->name }}</span>
26 @endforeach
27 </div>
28 @endif
29 </article>
30@endsection
31
32@push('scripts')
33 <script src="{{ asset('js/post-interactions.js') }}"></script>
34@endpush1{{-- Define section with content --}}
2@section('sidebar')
3 <p>Default sidebar content</p>
4@endsection
5
6{{-- Show section (in parent) --}}
7@yield('content')
8
9{{-- Show section with default --}}
10@yield('sidebar', 'Default sidebar')
11
12{{-- Show section and allow appending --}}
13@section('sidebar')
14 <p>Parent sidebar</p>
15@show
16
17{{-- Child can append to section --}}
18@section('sidebar')
19 @parent
20 <p>Child additional content</p>
21@endsection1{{-- Include a view --}}
2@include('partials.header')
3
4{{-- Include with data --}}
5@include('partials.alert', ['type' => 'success', 'message' => 'Saved!'])
6
7{{-- Include if exists --}}
8@includeIf('partials.optional-widget')
9
10{{-- Include when condition is true --}}
11@includeWhen($user->isAdmin(), 'partials.admin-panel')
12
13{{-- Include unless condition is true --}}
14@includeUnless($user->isGuest(), 'partials.user-menu')
15
16{{-- Include first available view --}}
17@includeFirst(['partials.custom', 'partials.default'])**Partial Example (resources/views/partials/alert.blade.php):**
1<div class="alert alert-{{ $type }}">
2 {{ $message }}
3</div>Include a view for each item in an array:
1@each('partials.product', $products, 'product')
2
3{{-- With empty view --}}
4@each('partials.product', $products, 'product', 'partials.no-products')**Product Partial (resources/views/partials/product.blade.php):**
1<div class="product">
2 <h3>{{ $product->name }}</h3>
3 <p>${{ $product->price }}</p>
4</div>Class-Based Component:
1// app/View/Components/Alert.php
2namespace App\View\Components;
3
4use Illuminate\View\Component;
5
6class Alert extends Component
7{
8 public function __construct(
9 public string $type = 'info',
10 public ?string $message = null
11 ) {}
12
13 public function render()
14 {
15 return view('components.alert');
16 }
17}**Component View (resources/views/components/alert.blade.php):**
1<div class="alert alert-{{ $type }}" role="alert">
2 @if($message)
3 {{ $message }}
4 @else
5 {{ $slot }}
6 @endif
7</div>1{{-- With attributes --}}
2<x-alert type="success" message="Operation completed!" />
3
4{{-- With slot --}}
5<x-alert type="danger">
6 <strong>Error!</strong> Something went wrong.
7</x-alert>
8
9{{-- With named slots --}}
10<x-card>
11 <x-slot:header>
12 <h2>Card Title</h2>
13 </x-slot:header>
14
15 <p>Card content goes here</p>
16
17 <x-slot:footer>
18 <button>Action</button>
19 </x-slot:footer>
20</x-card>Create components without PHP classes:
**Create (resources/views/components/button.blade.php):**
1@props(['type' => 'button', 'variant' => 'primary'])
2
3<button type="{{ $type }}" {{ $attributes->merge(['class' => "btn btn-$variant"]) }}>
4 {{ $slot }}
5</button>Use:
1<x-button variant="success" class="mt-4">
2 Save Changes
3</x-button>
4
5{{-- Renders: --}}
6<button type="button" class="btn btn-success mt-4">
7 Save Changes
8</button>1<form method="POST" action="{{ route('posts.store') }}">
2 @csrf
3
4 <div class="form-group">
5 <label for="title">Title</label>
6 <input type="text"
7 id="title"
8 name="title"
9 value="{{ old('title') }}"
10 class="@error('title') is-invalid @enderror">
11
12 @error('title')
13 <div class="invalid-feedback">{{ $message }}</div>
14 @enderror
15 </div>
16
17 <div class="form-group">
18 <label for="content">Content</label>
19 <textarea id="content"
20 name="content"
21 class="@error('content') is-invalid @enderror"
22 >{{ old('content') }}</textarea>
23
24 @error('content')
25 <div class="invalid-feedback">{{ $message }}</div>
26 @enderror
27 </div>
28
29 <button type="submit">Create Post</button>
30</form>HTML forms don't support PUT, PATCH, or DELETE methods. Use @method:
1<form method="POST" action="{{ route('posts.update', $post) }}">
2 @csrf
3 @method('PUT')
4
5 {{-- Form fields --}}
6
7 <button type="submit">Update Post</button>
8</form>
9
10<form method="POST" action="{{ route('posts.destroy', $post) }}">
11 @csrf
12 @method('DELETE')
13
14 <button type="submit">Delete Post</button>
15</form>1{{-- Display all errors --}}
2@if ($errors->any())
3 <div class="alert alert-danger">
4 <ul>
5 @foreach ($errors->all() as $error)
6 <li>{{ $error }}</li>
7 @endforeach
8 </ul>
9 </div>
10@endif
11
12{{-- Display specific field error --}}
13@error('email')
14 <span class="error">{{ $message }}</span>
15@enderror
16
17{{-- Check if field has error --}}
18@if ($errors->has('password'))
19 <div class="error">{{ $errors->first('password') }}</div>
20@endif1{{-- Safe JSON encoding --}}
2<script>
3 var user = @json($user);
4 var settings = @json($settings, JSON_PRETTY_PRINT);
5</script>1{{-- Conditional classes --}}
2<div @class([
3 'alert',
4 'alert-success' => $success,
5 'alert-danger' => !$success,
6 'font-bold' => true
7])>
8 Status message
9</div>
10
11{{-- Conditional styles --}}
12<div @style([
13 'background-color: red' => $error,
14 'color: white' => $highContrast
15])>
16 Content
17</div>1{{-- Checkbox --}}
2<input type="checkbox"
3 name="active"
4 value="1"
5 @checked(old('active', $user->active))>
6
7{{-- Radio --}}
8<input type="radio"
9 name="type"
10 value="admin"
11 @checked($user->type === 'admin')>
12
13{{-- Select option --}}
14<select name="role">
15 @foreach($roles as $role)
16 <option value="{{ $role->id }}" @selected(old('role') == $role->id)>
17 {{ $role->name }}
18 </option>
19 @endforeach
20</select>
21
22{{-- Disabled --}}
23<button @disabled($user->isGuest())>
24 Submit
25</button>
26
27{{-- Readonly --}}
28<input type="text" @readonly($user->isGuest())>
29
30{{-- Required --}}
31<input type="email" @required($field->isRequired())>1@switch($status)
2 @case('pending')
3 <span class="badge badge-warning">Pending</span>
4 @break
5
6 @case('approved')
7 <span class="badge badge-success">Approved</span>
8 @break
9
10 @case('rejected')
11 <span class="badge badge-danger">Rejected</span>
12 @break
13
14 @default
15 <span class="badge badge-secondary">Unknown</span>
16@endswitch1@php
2 $total = 0;
3 foreach ($items as $item) {
4 $total += $item->price;
5 }
6@endphp
7
8<p>Total: ${{ number_format($total, 2) }}</p>In a Service Provider:
1namespace App\Providers;
2
3use Illuminate\Support\Facades\Blade;
4use Illuminate\Support\ServiceProvider;
5
6class AppServiceProvider extends ServiceProvider
7{
8 public function boot(): void
9 {
10 // Simple directive
11 Blade::directive('datetime', function ($expression) {
12 return "<?php echo ($expression)->format('m/d/Y H:i'); ?>";
13 });
14
15 // Directive with parameters
16 Blade::directive('money', function ($expression) {
17 return "<?php echo '\$' . number_format($expression, 2); ?>";
18 });
19
20 // If directive
21 Blade::if('admin', function () {
22 return auth()->check() && auth()->user()->isAdmin();
23 });
24
25 // Unless directive
26 Blade::if('guest', function () {
27 return auth()->guest();
28 });
29 }
30}1{{-- Use datetime directive --}}
2<p>Created: @datetime($post->created_at)</p>
3
4{{-- Use money directive --}}
5<p>Price: @money($product->price)</p>
6
7{{-- Use custom if directive --}}
8@admin
9 <a href="/admin">Admin Panel</a>
10@endadmin
11
12@guest
13 <a href="/login">Please log in</a>
14@endguest1{{-- Good: Escaped --}}
2{{ $user->name }}
3
4{{-- Dangerous: Raw HTML --}}
5{!! $content !!} {{-- Only use when necessary --}}1<form method="POST">
2 @csrf {{-- Always include in POST forms --}}
3</form>1@error('email')
2 {{ $message }}
3@enderrorphp artisan view:clear@includeIf for optional views@once for scripts/styles that should only load onceBlade is Laravel's powerful, elegant templating engine that provides:
{{ }} for safe output, {!! !!} for raw HTML@csrf in forms@error directive for validation messages$loop)Blade makes creating views enjoyable and productive while maintaining security and performance!
Your progress is saved in this browser, on this device only.