Views: Blade Templates

Website Rebuild with Laravel

Chapter 4 · Views: Blade Templates

Django Rebuild 4 made a real point of what DTL structurally can't do — no arbitrary loops, no genuine tree-walking logic, nothing but a narrow tag vocabulary. Blade sits in a different place entirely: it's a real templating layer, but one that actually allows PHP to run inside it. That's not a small syntax difference — it changes what's even possible to attempt, and this chapter is honest about both what that buys you and why disciplined Laravel code mostly chooses not to use it anyway.

Template Inheritance: @extends and @section

{{-- resources/views/layouts/base.blade.php --}} <!DOCTYPE html> <html lang="en"> <head> <title>@yield('title', 'Osztromok.com')</title> </head> <body class="dark-theme"> <nav>@yield('breadcrumb')</nav> <main>@yield('content')</main> </body> </html>
{{-- resources/views/pages/show.blade.php --}} @extends('layouts.base') @section('title', $page->title) @section('breadcrumb') @foreach ($breadcrumb as $crumb) <a href="/{{ $crumb->full_path }}/">{{ $crumb->title }}</a> / @endforeach @endsection @section('content') <h1>{{ $page->title }}</h1> <div>{!! $page->body !!}</div> @endsection

@yield/@extends/@section do the identical structural job as Django's {% block %}/{% extends %} — a shell layout, filled in by a child template.

Blade's Real Difference: PHP Is Actually Allowed

Django Rebuild 4 built the breadcrumb walk in the Controller specifically because DTL couldn't do it in the template. Blade genuinely could:

{{-- This actually runs — DTL structurally could not do this --}} @php $breadcrumb = []; $node = $page; while ($node) { array_unshift($breadcrumb, $node); $node = $node->parent; } @endphp @foreach ($breadcrumb as $crumb) <a href="/{{ $crumb->full_path }}/">{{ $crumb->title }}</a> / @endforeach

@php/@endphp is a real block of genuine PHP, executed directly inside the template, with full access to loops, conditionals, and any expression the language allows. This isn't a workaround or an edge case — it's an intentional, documented Blade feature.

Why the Controller Still Wins Anyway

The central fact this chapter is built on
Blade's capability difference from DTL is genuine — the code above actually runs. But disciplined Laravel code still keeps logic like this in the Controller almost all the time, exactly like Django's own code does. The destination — thin views, real logic living elsewhere — is usually the same. What's different is the enforcement mechanism: Django's DTL makes the tree-walking loop structurally impossible to write in a template at all. Blade makes it possible, and relies entirely on developer discipline and community convention to keep it out of templates anyway. One is a language limitation; the other is a norm you have to choose to follow.
// app/Http/Controllers/PageController.php — the recommended version $breadcrumb = []; $node = $page; while ($node) { array_unshift($breadcrumb, $node); $node = $node->parent; } return view('pages.show', ['page' => $page, 'breadcrumb' => $breadcrumb]);

Auto-Escaping and {!! !!}: Blade's Own |safe

{{ $page->title }} auto-escapes by default, exactly like Django's {{ }} and React's JSX. {!! $page->body !!} is Blade's own raw-output syntax, the direct equivalent of Django's |safe filter — and the same trust-boundary reasoning applies without modification: appropriate here specifically because page.body is written exclusively by the authenticated admin, never acceptable for anything a visitor could submit through a form.

Three Points on a Spectrum

Next.js (React/JSX)Django (DTL)Laravel (Blade)
Logic in the view layerFull JavaScript, no restriction at allStructurally impossible — tags and filters onlyGenuinely possible via @php, discouraged by convention
What enforces "thin views"Developer discipline, same as LaravelThe language itselfDeveloper discipline, same as Next.js/React

Django is the outlier here, not Laravel — both Next.js and Laravel allow real logic in the view layer and rely on convention to keep it disciplined; Django is the one framework in this course's own trio that makes the restriction structural.

Hands-On Exercises

Exercise 1

Explain the genuine capability difference between Blade and Django's DTL, illustrated by the breadcrumb example. What's actually possible in Blade that was structurally impossible in DTL?

📄 View solution
Exercise 2

Even though Blade can embed the breadcrumb loop directly via @php, this chapter still recommends building it in the Controller. Explain why, and explain what's different about how Django enforces the same outcome versus how Laravel does.

📄 View solution
Exercise 3

Explain the parallel between Blade's {!! !!} and Django's |safe filter, including why the identical trust-boundary reasoning (admin-authored content only) applies to both.

📄 View solution

Chapter 4 Quick Reference

  • @extends / @section / @yield — Blade's own template inheritance, structurally the same job as Django's {% extends %}/{% block %}
  • @php / @endphp — real, executable PHP inside a template — a genuine capability Django's DTL doesn't have
  • The Controller still wins — by convention, not by language limitation; Blade's "thin views" discipline is a choice, Django's is enforced
  • {{ }} auto-escapes by default; {!! !!} — Blade's own direct equivalent of Django's |safe, same trust boundary
  • Django is the outlier — both Next.js and Laravel permit real view-layer logic and rely on convention; Django alone makes it structurally impossible
  • Next chapter: Styling — Dark Theme