Module 3: The Presentation Layer
Views and the Blade Templating Engine.
Bringing Your Data to Life
Welcome to Module 3! So far, you've set up a Laravel project and learned how to manage its data with Eloquent. But how do you actually show that data to a user? That's the job of the "View" layer, and in Laravel, this is powered by the brilliant Blade Templating Engine. Blade allows you to write clean, readable, and powerful templates that combine HTML with your application's data. It provides elegant shortcuts for common PHP functions and promotes code reuse through layouts, saving you from writing messy PHP inside your HTML.
1Blade Fundamentals: From Data to Display
At its core, Blade is about one thing: getting data from your back-end logic into your front-end HTML. All Blade files are stored in the `resources/views` directory and use the `.blade.php` extension.
Displaying Data
The most common thing you'll do is "echo" data. Instead of writing ``, Blade gives you a much cleaner syntax: `{{ $variable }}`.
<h1>Post Title: {{ $post->title }}</h1>
An incredibly important feature of the `{{ }}` syntax is that it automatically protects you from XSS attacks by passing the data through PHP's `htmlspecialchars` function. This prevents malicious users from injecting harmful scripts into your pages.
Control Structures
Blade provides simple directives for all of PHP's control structures, making your views far more readable.
If Statements:
@if (count($posts) === 1)
I have one post!
@elseif (count($posts) > 1)
I have multiple posts!
@else
I don't have any posts.
@endif
Loops: The `@foreach` directive is perfect for iterating over data collections from your database.
<ul>
@foreach ($posts as $post)
<li>{{ $post->title }}</li>
@endforeach
</ul>
2Template Inheritance: The DRY Principle
DRY stands for "Don't Repeat Yourself". Most websites have a common layout: a header, a navigation bar, a main content area, and a footer. It would be incredibly inefficient to rewrite this structure for every single page. Blade solves this with template inheritance.
Creating a Master Layout
First, we create a master layout file. Let's create a new folder `resources/views/layouts` and add a file called `app.blade.php`. This file will contain all the shared HTML.
<!-- resources/views/layouts/app.blade.php -->
<!DOCTYPE html>
<html>
<head>
<title>My Awesome Blog</title>
</head>
<body>
<header>
<h1>Website Header</h1>
</header>
<main>
@yield('content')
</main>
<footer>
<p>© 2025 My Awesome Blog</p>
</footer>
</body>
</html>
The key here is the `@yield('content')` directive. This is a placeholder that tells Blade: "A child page will provide the content for this section."
Extending the Layout
Now, we can create a page-specific view, like `resources/views/posts/index.blade.php`, that "extends" the master layout and provides the content.
<!-- resources/views/posts/index.blade.php -->
@extends('layouts.app') // Tells Blade to use the app.blade.php layout
@section('content') // Starts defining the 'content' section
<h2>All Blog Posts</h2>
<p>Here is a list of all our posts!</p>
@endsection // Ends the section
When Laravel renders this view, it will take the content from the `@section` and inject it into the `@yield` placeholder in the master layout, giving you a complete HTML page. This is an incredibly powerful and clean way to manage your UIs.
3Putting It All Together: A Practical Example
Let's connect everything we've learned from all three modules. We will create a page that fetches all posts from the database (Module 2) and displays them in a Blade view (Module 3).
1. Create a Route
First, define a URL for our posts page. Open `routes/web.php` and add a new route. We'll link this route to a method in a controller, which is the best practice for organizing your code.
use App\Http\Controllers\PostController;
Route::get('/posts', [PostController::class, 'index']);
2. Create a Controller
A controller's job is to handle incoming requests, fetch data, and return a response (like a view). Let's create a `PostController` using Artisan:
php artisan make:controller PostController
This creates the file `app/Http/Controllers/PostController.php`. Now, let's add the `index` method to it. Inside this method, we'll use our `Post` model to get all posts and then pass them to our Blade view.
<?php
namespace App\Http\Controllers;
use App\Models\Post; // Important: Import the Post model
use Illuminate\Http\Request;
class PostController extends Controller
{
public function index()
{
$posts = Post::all(); // 1. Fetch all posts from the database
return view('posts.index', ['posts' => $posts]); // 2. Return the view and pass the data
}
}
The `view()` function takes two arguments: the name of the view file (using dot notation for directories) and an array of data to make available to that view.
3. Create the View
Finally, let's update our `resources/views/posts/index.blade.php` file to use the `$posts` variable we passed from the controller.
@extends('layouts.app')
@section('content')
<h1>Our Blog Posts</h1>
@forelse ($posts as $post)
<div class="post-item">
<h2>{{ $post->title }}</h2>
<p>{{ $post->content }}</p>
</div>
<hr>
@empty
<p>No posts found!</p>
@endforelse
@endsection
(Note: `@forelse` is a handy Blade directive that's like `@foreach` but includes an `@empty` block that runs if the array is empty.)