Blade is Laravel's powerful, lightweight templating engine. Files end in .blade.php and live in resources/views/.
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
| Syntax | Compiles To | Note |
|---|---|---|
{{ $var }} | <?= e($var) ?> | HTML-escaped (safe) |
{!! $var !!} | <?= $var ?> | Raw output (unsafe for user data) |
{{-- comment --}} | nothing | Not rendered in HTML source |
@{{ literal }} | {{ literal }} | Escaped for Vue/Angular use |
<!-- 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>
{{ }} for user-generated content. Only use {!! !!} for HTML you generate yourself (e.g., a Markdown parser output).@if ($user->isAdmin())
<span class="badge">Admin</span>
@elseif ($user->isModerator())
<span class="badge">Moderator</span>
@else
<span>Member</span>
@endif
@unless (Auth::check())
<a href="/login">Please log in</a>
@endunless
@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
@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 ($posts as $post)
<p>{{ $post->title }}</p>
@empty
<p>No posts found.</p>
@endforelse
@for ($i = 1; $i <= 5; $i++)
<p>Item {{ $i }}</p>
@endfor
@while ($condition)
<p>Looping...</p>
@endwhile
| Property | Description |
|---|---|
$loop->index | Zero-based iteration index |
$loop->iteration | One-based iteration number |
$loop->remaining | Items remaining in loop |
$loop->count | Total items in collection |
$loop->first | True on first iteration |
$loop->last | True on last iteration |
$loop->even / odd | True on even/odd iterations |
$loop->depth | Nesting level of current loop |
$loop->parent | Parent loop's $loop in nested loops |
<!DOCTYPE html>
<html>
<head>
<title>@yield('title', 'My App')</title>
@stack('styles')
</head>
<body>
<nav>...navigation...</nav>
<main>
@yield('content')
</main>
<footer>@yield('footer', '© 2024')</footer>
@stack('scripts')
</body>
</html>
@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('partials.navbar')
@include('partials.alert', ['type' => 'success', 'msg' => 'Saved!'])
@includeIf('partials.sidebar') // only if file exists
@includeWhen($user->isAdmin(), 'admin.bar') // conditional
<!-- 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>
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');
}
}
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>
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
@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>
@php blocks minimal — move complex logic to controllers, view composers, or helper classes instead.| Directive | Purpose |
|---|---|
@extends('layout') | Inherit from a parent layout |
@section('name') ... @endsection | Define a named section |
@yield('name') | Output a section in layout |
@parent | Include parent section content |
@include('view') | Include a partial view |
@if / @elseif / @else / @endif | Conditional rendering |
@unless ... @endunless | Inverse of @if |
@isset / @endisset | Check variable is set |
@empty / @endempty | Check variable is empty |
@foreach / @endforeach | Loop over collection |
@forelse / @empty / @endforelse | Loop with empty fallback |
@for / @endfor | C-style for loop |
@while / @endwhile | While loop |
@break / @continue | Loop flow control |
@csrf | CSRF hidden token field |
@method('PUT') | HTTP method spoofing |
@auth / @endauth | Show if authenticated |
@guest / @endguest | Show if not authenticated |
@can('action', $model) | Show if user has permission |
@push / @endpush | Push content to a stack |
@stack('name') | Output a stack in layout |
@php ... @endphp | Raw PHP block |
@dump($var) | Debug dump a variable |
@dd($var) | Dump and die |