It’s time to make things look a little more pretty than we have so far. So far, we have been simply outputting data to the web browser with no formatting or special CSS applied in any way. In fact, this is a good way to begin things, as it has allowed us to stay completely focused on the core concepts of Laravel. Soon however, your web designer side wants to contribute to the game to get things looking better. This is what we will go after in this tutorial by looking at how we can set up a layouts template system so we can share common html markup and assets across multiple views. Let’s take a look at this idea now.
Add a layouts folder to resources/views
To begin, we will create a layouts folder that will reside in the resources/views directory. In here, we can store our master layout file. We can also store partial view files if we like. Partial view files would be things like a footer, or a header. Here we go.
Note that we already have a games folder in the views directory. This holds our current index.blade.php
and show.blade.php
files. Now that we have a layouts folder, we can put a master template in there. By convention, it is usually named master.blade.php
so let’s create that file now and populate with some Bootstrap boilerplate.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Games</title>
<link href="/css/bootstrap.min.css" rel="stylesheet">
<link href="/css/sticky-footer.css" rel="stylesheet">
</head>
<body>
<nav class="navbar navbar-toggleable-md navbar-light bg-faded">
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse"
data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<a class="navbar-brand" href="#">We Like Games</a>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item">
<a class="nav-link" href="games">List Games</a>
</li>
</ul>
</div>
</nav>
<div class="container">
@yield('content')
</div>
<footer class="footer">
<div class="container">
<span class="text-muted">We Like Games</span>
</div>
</footer>
<script src="/js/jquery-3.1.1.slim.min.js"></script>
<script src="/js/tether.min.js"></script>
<script src="/js/bootstrap.min.js"></script>
</body>
</html>
Extract Repeated Content To A Layout File
We can now look at the view files that we already have in our system. We have index.blade.php
and show.blade.php
, and they have overlapping, or repeated markup. There’s really no need to have to worry about rendering out all that boilerplate for every new view file we need to make use of. So let’s go ahead and extract that repeating markup. First, we can take the index.blade.php
file and change it from this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Games</title>
</head>
<body>
<ul>
@foreach($games as $game)
<li><a href="/games/{{ $game->id }}">{{ $game->title }}</a></li>
@endforeach
</ul>
</body>
</html>
To this:
@extends('layouts.master')
@section('content')
<ul>
@foreach($games as $game)
<li><a href="/games/{{ $game->id }}">{{ $game->title }}</a></li>
@endforeach
</ul>
@endsection
And with that, we have a decent little layout going.
Note that we have downloaded and installed a few files into the public folder. We have placed bootstrap.min.css and sticky-footer.css in public/css as well as jquery-3.1.1.slim.min.js, tether.min.js, and bootstrap.min.js in public/js. This approach is kind of the poor mans way to assemble front end assets, but it’s good enough for this tutorial.
Yield, Extends, Section
Yield
It makes sense to talk a little bit about the yield, extends, and section keywords with regard to blade now. In our master.blade.php
file, there was a line that said @yield(‘content’). This tells Laravel that for any file that extends master.blade.php
, look for a section of markup that is identified as ‘content’, and insert that markup here.
Extends
The next thing we did was to visit our index.blade.php
file and remove the boilerplate. In it’s place, we wrote out something like @extends(‘layouts.master’). This tells Laravel that we want to make use of all the boilerplate now contained in master.blade.php
, but we don’t want to manually type it all out here. So in the index.blade.php
file, we are now in essence building upon what is contained in master.blade.php
.
Section
Finally, we added a snippet to our index.blade.php
file that began with @section(‘content’) and then was subsequently rounded out with @endsection. This defines an area of markup that is identified by the word ‘content’. Remember how in our master.blade.php
file, we have a part of the markup that uses the statement of @yield(‘content’). Well now that we have a section defined in our index.blade.php
file which is identified as ‘content’, Laravel knows to grab that markup which exists between @section(‘content’) and @endsection, and insert it right where the @yield(‘content’) statement is.
Layout File For Single Page View
We have a decent looking page that lists all our games. Let’s now also fix up the show.blade.php
view file so that things look nice when we drill down as well. We’ll change our existing show.blade.php
file from this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Game</title>
</head>
<body>
{{ $game->title }} is published by {{ $game->publisher }}
</body>
</html>
To this:
@extends('layouts.master')
@section('content')
<div class="card" style="width: 270px;margin: 5px">
<img class="card-img-top" src="/{{ $game->title }}.png" alt="Card image cap">
<div class="card-block">
<h3 class="card-title">{{ $game->title }}</h3>
<p class="card-text">{{ $game->title }} is published by {{ $game->publisher }}</p>
<a href="/games" class="btn btn-primary">List Games</a>
</div>
</div>
@endsection
In the show.blade.php
file, we make use of bootstrap 4 cards which are new and look pretty nice. We have also placed an image for each game in the public folder for a quick and dirty example of how images look in bootstrap 4 cards. We simply use the title of each game as the name of the image file. This way, we can set the src for the image to /{{ $game->title }}.png and everything works when we click on each game. Check it out!
Using Partials To Clean Up Layout Files
Things are looking good, but as it stands now, our master.blade.php
file is still a bit bloated now that we have added so much to it. We can make use of partials to extract logical groups of markup into their own files. Once they are extracted, we simply use the @include directive in the main master.blade.php
file to make use of them. We will create a partials directory in the resources/views folder now. We’ll also place three new files in that partials directory to hold the markup for our head section, our navbar, and our footer section.
resources/views/partials/headcontent.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Games</title>
<link href="/css/bootstrap.min.css" rel="stylesheet">
<link href="/css/sticky-footer.css" rel="stylesheet">
</head>
resources/views/partials/navbar.blade.php
<nav class="navbar navbar-toggleable-md navbar-light bg-faded">
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse"
data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<a class="navbar-brand" href="#">We Like Games</a>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item">
<a class="nav-link" href="games">List Games</a>
</li>
</ul>
</div>
</nav>
resources/views/partials/footercontent.blade.php
<footer class="footer">
<div class="container">
<span class="text-muted">We Like Games</span>
</div>
</footer>
<script src="/js/jquery-3.1.1.slim.min.js"></script>
<script src="/js/tether.min.js"></script>
<script src="/js/bootstrap.min.js"></script>
</body>
</html>
New Master Layout
With all of our partials now defined, we can simplify our master.blade.php file to something as simple as this, and everything still works great.
@include('partials.headcontent')
<body>
@include('partials.navbar')
<div class="container">
@yield('content')
</div>
@include('partials.footercontent')
Creating A Layouts Template In Laravel Summary
In this tutorial, we had a look at how to structure the layout of a simple web application using a master template. We learned about how blade makes use of various keywords such as yield, include, section, and endsection to make this process work. Once we have a nice master template, we can create new view files with minimal code by simply using the extends keyword to build a new view on the shoulders of our master template. In that view file which extends the master, we can make use of the yield keyword to denote where we want content to be inserted into the master layout. We also saw how to make use of partials and include statements to make the overall structure much more compartmentalized and easier to reason about. Let’s here it for master layouts!