January 13, 2024 · 5 min read · 1,161 views
We're excited to announce that we have updated all of our blog post examples to reflect the new Laravel 11 version! Our previous examples were based on Laravel 10, but with the release of Laravel 11, we wanted to ensure that our readers have access to the most up-to-date information and examples.
When combined with Laravel Breeze, you get a simple yet effective starting point for authentication views and a clear example of Blade in action. Let's dive into the basics of Laravel Blade and how it's used within Breeze to create a seamless user experience.
Blade is Laravel's built-in templating engine, designed to provide developers with a convenient way to write HTML templates while also allowing the use of PHP. It offers an expressive syntax for extending layouts, displaying data, and constructing reusable components.
Blade templates use a mix of HTML and Blade directives – special tokens that Blade recognizes and converts into PHP code. Here are some of the fundamental directives:
@extends
: Indicates that the template extends a layout.
@section
and @endsection
: Define a section of content.
@yield
: Used in layouts to display the content of a section.
@include
: Includes another Blade file within the template.
{{ }}
: Echoes data, automatically escaping HTML entities for security.
@if
, @elseif
, @else
, @endif
: Control structures for conditional statements.
@foreach
, @endforeach
: Loops through a data array.
Blade allows you to create a master layout that serves as a template for your application's look. Here's a simple example of a layout:
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Head Contents -->
</head>
<body>
<header>
<!-- Header Content -->
</header>
<main>
@yield('content')
</main>
<footer>
<!-- Footer Content -->
</footer>
</body>
</html>
Using @yield('content')
, you define a placeholder for where the content of your child views will be injected.
Laravel Breeze simplifies authentication by providing a minimal and clean starting point, including Blade views for login, registration, password reset, and email verification. Let's see how Blade and Breeze work together.
After installing Breeze, you'll notice that the views are stored in resources/views/auth
. Here's an example of how a login form might look using Blade:
@extends('layouts.app')
@section('content')
<div>
<form method="POST" action="{{ route('login') }}">
@csrf
<!-- Email Input -->
<div>
<label for="email">Email</label>
<input id="email" type="email" name="email" required autocomplete="email" autofocus>
</div>
<!-- Password Input -->
<div>
<label for="password">Password</label>
<input id="password" type="password" name="password" required>
</div>
<!-- Submit Button -->
<div>
<button type="submit">Login</button>
</div>
</form>
</div>
@endsection
In this template, we're extending the app
layout and defining the content section. We use Blade's @csrf
directive to include a CSRF token field in the form for security, and {{ route('login') }}
to generate the URL to the login route.
The screenshot below shows the Breeze Profile Edit page where we can modify the user data.
Blade also supports components, which are reusable pieces of the user interface. Breeze utilizes components to keep views DRY (Don't Repeat Yourself). For example, you might have a component for an input field:
<input {{ $attributes }}>
You can use this component in your forms like so:
<x-input id="email" type="email" name="email" required />
Let's create some of the views for our blog app example.
First, we need to create a new folder named posts
inside of the resources/views
folder. Then we create a new file index.blade.php
.
@extends('layouts.app')
@section('title', 'All Blog Posts')
@section('content')
<h1>All Blog Posts</h1>
<ul>
@forelse ($posts as $post)
<li>
<a href="{{ route('posts.show', $post) }}">{{ $post->title }}</a>
<p>{{ $post->created_at->toFormattedDateString() }}</p>
</li>
@empty
<li>No posts available.</li>
@endforelse
</ul>
@endsection
In this view, we're extending a main layout and then defining a section for the content. We loop through all the posts using @forelse
, which also handles the case where there are no posts. Each post title is a link to the single post view.
We create another file in the same directory, show.blade.php
:
@extends('layouts.app')
@section('title', $post->title)
@section('content')
<article>
<h1>{{ $post->title }}</h1>
<p>Published {{ $post->created_at->diffForHumans() }}</p>
<div>{{ $post->content }}</div>
{{-- Check if there are any tags --}}
@if($post->tags->isNotEmpty())
<p>Tags:</p>
<ul>
@foreach($post->tags as $tag)
<li>{{ $tag->name }}</li>
@endforeach
</ul>
@endif
</article>
<a href="{{ route('posts.index') }}">Back to all posts</a>
@endsection
In the single post view, we show the post title, publication date, and content. The diffForHumans()
will display the date as 5 days ago
or 2 years ago
depending on the time difference between the current moment and the post date.
The screenshot below displays the Single Post page of a randomly selected post that we tested.
We create another file create.blade.php
for displaying the form to create a new post.
@extends('layouts.app')
@section('title', 'Create New Post')
@section('content')
<h1>Create New Post</h1>
<form method="POST" action="{{ route('posts.store') }}">
@csrf
<div>
<label for="title">Title</label>
<input type="text" id="title" name="title" value="{{ old('title') }}" required>
@error('title')
<p>{{ $message }}</p>
@enderror
</div>
<div>
<label for="content">Content</label>
<textarea id="content" name="content" required>{{ old('content') }}</textarea>
@error('content')
<p>{{ $message }}</p>
@enderror
</div>
<div>
<label for="tags">Tags</label>
<select name="tags[]" id="tags" multiple>
@foreach (\App\Models\Tag::all() as $tag)
<option value="{{ $tag->id }}" {{ in_array($tag->id, old('tags', [])) ? 'selected' : '' }}>{{ $tag->name }}</option>
@endforeach
</select>
</div>
<div>
<button type="submit">Publish Post</button>
</div>
</form>
@endsection
In the create post view, we have a form with fields for the post title and content. We use the @csrf
directive to protect against cross-site request forgery. The @error
directive is used to display validation errors for each field. The old()
function is used to repopulate the fields with the previously entered data in case of a validation error.
Also, change function of the store in PostController
:
<?php
// Store a newly created blog post
public function store(Request $request)
{
$validatedData = $request->validate([
'title' => 'required|max:255',
'content' => 'required',
]);
$tags = $request->validate([
'tags' => 'required|array',
'tags.*' => 'exists:tags,id',
])['tags'];
// the new post belongs to the authenticated user
$post = auth()->user()->posts()->create($validatedData);
// we add tags to the post by using the sync() method
$post->tags()->sync($tags['tags']);
// PostPublished::dispatch($post);
return redirect()->route('posts.show', $post);
}
We will create a new folder in the views
directory named as layouts
. Then we will create a new file inside of that directory app.blade.php
.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@yield('title') - My Blog</title>
</head>
<body>
<header>
<nav>
<a href="{{ url('/') }}">Home</a>
<a href="{{ route('posts.index') }}">Blog</a>
<a href="{{ route('posts.create') }}">Write a Post</a>
</nav>
</header>
<main>
@yield('content')
</main>
<footer>
<p>© My Blog</p>
</footer>
</body>
</html>
The layout file provides a basic structure for the HTML pages, including a header with navigation links, a main content area where the individual views will be rendered, and a footer. The @yield
directive is used to insert the content from the child views into the layout.
These Blade views provide the basic functionality for a blog to display posts and allow users to create new ones. You can customize the HTML and styling to match your blog's design and requirements.
Blade is a powerful templating engine that makes writing and managing your web apps HTML content a breeze, especially when paired with Laravel Breeze for authentication. By mastering Blade's directives, layout system, and components, you can create efficient and elegant views for your Laravel app.
This article is part of our series Laravel 11 for Beginners: A Step-by-Step Guide to Learn the Concepts.
If you need help with a Laravel project let's get in touch.
Lucky Media is proud to be recognized as a Top Laravel Development Agency
Technologies:
Related Posts
Stay up to date
Be updated with all news, products and tips we share!