0

Blade — Laravel's template engine and what the name means

Beginner5 min read·eng-14-016

Concept

Blade — Laravel's template engine for rendering HTML views. The name is a play on the "sharp" PHP alternative to raw <?php ?> tags — it "cuts through" boilerplate syntax.

What Blade provides over plain PHP:

  • Cleaner syntax: {{ $variable }} instead of <?php echo htmlspecialchars($variable) ?>.
  • Template inheritance: @extends('layout') + @section() + @yield() for master layouts.
  • Components: <x-alert type="error">{{ $message }}</x-alert> — reusable HTML components.
  • Control flow directives: @if, @foreach, @forelse, @switch, @unless, @empty.
  • Includes: @include('partial'), @includeWhen($condition, 'partial').
  • CSRF: @csrf inserts the hidden CSRF token field.
  • Stack: @stack('scripts') + @push('scripts') — inject content from child templates into named stacks.

Security by default: {{ $variable }} escapes HTML (htmlspecialchars). Use {!! $variable !!} only for intentionally unescaped HTML (trusted sources only — never user input).

Compilation: Blade templates are compiled to plain PHP and cached in storage/framework/views/. The compiled file is just PHP with echo statements. Recompiles when the template changes.

Livewire integration: Livewire is built on Blade. Livewire components are Blade templates with PHP logic that re-render reactively via Ajax.

When NOT to use Blade: If your frontend is a SPA (Vue, React, Next.js), Blade is irrelevant. Your backend returns JSON from API endpoints instead. Blade is for server-rendered HTML.

Code Example

blade
{{-- resources/views/layouts/app.blade.php --}}
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <title>@yield('title', 'My App')</title>
    @stack('styles')
</head>
<body>
    @include('partials.nav')          {{-- include a partial --}}

    <main>
        @yield('content')             {{-- child views inject here --}}
    </main>

    @stack('scripts')
</body>
</html>
blade
{{-- resources/views/users/index.blade.php --}}
@extends('layouts.app')

@section('title', 'Users')

@section('content')
    <h1>Users</h1>

    @csrf        {{-- generates <input type="hidden" name="_token" value="..."> --}}

    {{-- Escaped output — safe from XSS --}}
    <p>Welcome, {{ $user->name }}</p>
    {{-- equivalent to: <?php echo htmlspecialchars($user->name) ?> --}}

    {{-- Unescaped — ONLY for trusted HTML --}}
    <p>{!! $article->rendered_html !!}</p>

    {{-- Control flow --}}
    @if ($users->isEmpty())
        <p>No users found.</p>
    @else
        @foreach ($users as $user)
            <div>{{ $user->name }}</div>
        @endforeach
    @endif

    {{-- @forelse — combines foreach with empty check --}}
    @forelse ($users as $user)
        <div>{{ $user->name }}</div>
    @empty
        <p>No users found.</p>
    @endforelse
@endsection

@push('scripts')
    <script>console.log('Users page loaded');</script>
@endpush
blade
{{-- resources/views/components/alert.blade.php (Blade component) --}}
@props(['type' => 'info', 'message'])
<div class="alert alert-{{ $type }}">
    {{ $message }}
</div>
blade
{{-- Using the component --}}
<x-alert type="error" message="Something went wrong" />
<x-alert type="success">{{ __('Saved successfully') }}</x-alert>