This title was written for Laravel version 4. If you're looking for material on the latest version of Laravel, then please check out Code Smart.
In this chapter, we will learn how to master the Blade. You will need it. In order to claim your rightful place as a PHP artisan you will need to challenge and defeat High Lord Otwell in armed combat.
It’s a rite of passage. Only then will you be able to take your rightful place amongst the Laravel council, and earn a spot at Phil Sturgeon’s drinking table.
Once a month, us Council members ride out to the PHP battleground sat atop our fearsome Laravel riding pandas, to do battle with the developers of other frameworks. If you want to ride into battle alongside us, and fight for the honour of Laravel you must learn to master the Blade.
Well, must is a strong word I suppose. I mean, you could also master Blade templating. It’s not quite as extravagant, and there are no fierce riding pandas involved. It is pretty handy though, and perhaps more suited to coder types than hardcore battle?
Yeah that’s settled then, let’s have a look at Blade templating.
You might be wondering about the name ‘Blade’? Well so was I as I wrote this chapter, so I decided to ask Taylor. It turns out that the .NET web development platform has a templating tool called ‘Razor’, from which much of the Blade syntax was derived. Razor..blade.. razorblade. That’s it. Nothing funny there really, sorry. :(
Actually forget what I just told you, let’s reinvent that story. Just between us. The templating language was named after Taylor’s alter ego ‘Blade’ back during his days of Vampire hunting. That’s the real story.
Right, let’s make a template.
Creating Templates
I know, I know, I already taught you how to create views right? They are really useful for separating the visual aspect of your application from its logic, but, it doesn’t mean they can’t be improved upon.
The problem with standard PHP templates is that we have to insert those ugly PHP tags within them to use the data that our logic portions have provided. They look out of place within our neat HTML templates. They soil them! It makes me so angry... I could... I could. No, let me be for a moment.
Erm...
It’s ok, my rage has settled now. Let’s create a Blade template to get that nasty PHP mess out of the way. To get started we will need to make a new file. Blade templates live in the same location as our standard view files. The only difference is that they use the .blade.php
extension rather than just .php
.
Let’s create a simple template.
<!-- app/views/example.blade.php -->
<h1>Dear Lord Otwell</h1>
<p>I hereby challenge you to a duel for the honour of Laravel.</p>
<?php echo $squirrel; ?>
Here we have our blade template, looks kinda similar to what we have seen already right? That’s because Blade first parses the file as PHP. You see our $squirrel
? Every view file must have a squirrel. OK, that’s not true, but it does show that PHP can be parsed just as before.
We can show this using the same syntax as we would for a normal view. You might have assumed that it would require passing example.blade
to the View::make()
method, but that would be incorrect.
<?php
// app/routes.php
Route::get('example', function()
{
return View::make('example');
});
See? Laravel knows what a Blade template is, and how to look for one. For this reason the View::make()
statement hasn’t changed at all. How convenient?!
Blade does have some tricks of its own however. Let’s take a look at the first one.
PHP Output
A lot of your templates will involve echoing out data provided by the logic portion of your application. Normally it would look something like this:
<!-- app/views/example.blade.php -->
<p><?php echo $taylorTheVampireSlayer; ?></p>
It’s not exactly verbose, but it could be improved upon. Let’s see how we can echo values using Blade templates.
<!-- app/views/example.blade.php -->
<p>{{ $taylorTheVampireSlayer }}</p>
Everything surrounded by {{
double curly brackets }}
is transformed into an echo by Blade when the template is processed. This is a much cleaner syntax, and a whole lot easier to type.
Since the Blade template directives are translated directly to PHP we can use any PHP code within these brackets, including methods.
<!-- app/views/example.blade.php -->
<p>{{ date('d/m/y') }}</p>
You don’t even need to provide the closing semi-colon. Laravel does that for you.
Sometimes you will want to protect yourself by escaping a value that you output. You might be familiar with using methods such as strip_tags()
and htmlentities()
for this purpose. Why? well consider the output of this template.
<!-- app/views/example.blade.php -->
<p>{{ '<script>alert(“CHUNKY BACON!”);</script>' }}</p>
What a nasty piece of Code! It would cause some Javascript to be injected into the page and a browser popup to be displayed containing the text ‘CHUNKY BACON!’. Bad _why! Nasty ruby developers are always trying to break our websites.
We have the power to protect our templates from the output though. If we were to use {{{
three curly brackets }}}
instead of {{
two }}
then our output will be escaped, the angular brackets will be converted to HTML entities, and the Javascript will show as text within the page. Harmless!
Let’s see this in action.
<!-- app/views/example.blade.php -->
<p>{{{ '<script>alert("CHUNKY BACON!");</script>' }}}</p>
All we have changed is the number of brackets around our nasty Javascript snippet. Let’s view the source of the page to see how it looks.
<!-- app/views/example.blade.php -->
<p><script>alert("CHUNKY BACON!");</script></p>
As you can see, the HTML tags and some other characters have been replaced with the equivalent HTML entities. Our website is saved!
Moving on!
Control Structures
PHP has a number of control structures. If statements, while, for and foreach loops. If you haven’t heard of these before then this book really isn’t the one for you!
Within templates you will most likely be familiar with using the alternative syntax for control structures using colons :
. Your if
statements will look like this:
<!-- app/views/example.blade.php -->
<? if ($something) : ?>
<p>Something is true!</p>
<? else : ?>
<p>Something is false!</p>
<? endif; ?>
Once again, these do the trick, but they aren’t very fun to type. They will slow you down, but fortunately for you, Blade will come to your rescue!
Here’s how the above snippet looks within a Blade template.
<!-- app/views/example.blade.php -->
@if ($something)
<p>Something is true!</p>
@else
<p>Something is false!</p>
@endif
That’s much cleaner, right? Let’s have a look at what we have stripped out. For a start, the PHP opening <?
and closing ?>
tags are gone. Those are probably the most complicated to type.
We can also strip out the colons :
and semi ;
colons. We don’t need those wasting space in our templates!
Lastly we have made an addition to the usual syntax. We have prefixed our control statement lines with an at @
symbol. In fact, all blade control structures and helper methods are prefixed with this symbol, so that the template compiler knows how to handle them.
Let’s add an elseif
to the mix for a further example.
<!-- app/views/example.blade.php -->
@if ($something == 'Red Panda')
<p>Something is red, white, and brown!</p>
@elseif ($something == 'Giant Panda')
<p>Something is black and white!</p>
@else
<p>Something could be a squirrel.</p>
@endif
We’ve added another statement into the mix, following the same rules of removing PHP tags, colons and semi colons, and adding the @
sign. Everything works perfectly.
Here’s a challenge. Try to picture a foreach
PHP loop represented with blade syntax. Close your eyes, picture it. Focus... focus!
Did it look like this?
<!-- app/views/example.blade.php -->
c~~p ,---------.
,---'oo ) \
( O O )/
`=^=' /
\ , . /
\\ |-----'| /
||__| |_|__|
No? Good, because that is a hippo. However, if it looked a little like the following snippet then you will get a cookie.
<!-- app/views/example.blade.php -->
@foreach ($manyThings as $thing)
<p>{{ $thing }}</p>
@endforeach
Enjoy your cookie! As you can see, we used the Blade {{
echo }}
syntax to output the loop value. A for loop looks just as you might imagine. Here is an example for reference.
<!-- app/views/example.blade.php -->
@for ($i = 0; $i < 999; $i++)
<p>Even {{ $i }} red pandas, aren't enough!</p>
@endfor
Simple, and exactly what you might have expected. The while loop follows the same rules, but I’m going to show a quick example to allow this to be a useful reference chapter.
<!-- app/views/example.blade.php -->
@while (isPretty($keiraKnightley))
<p>This loop probably won't ever end.</p>
@endwhile
Right, so you are the conditional master now. Nothing can phase you, right buddy? Not even PHP’s ‘unless’ condition.
Err Dayle, Ruby has that. I dunno if PHP ha..
OK, you caught me out. PHP doesn’t have an ‘unless’ condition. However, Blade has provided a helper to allow it. Let’s have a look at an example.
<!-- app/views/example.blade.php -->
@unless (worldIsEnding())
<p>Keep smiling.</p>
@endunless
Unless is the exact opposite of an if statement. An if statement checks if a condition equates to a true value, and then executes some logic. However, the unless statement will execute its logic only if the condition equates to false. You can think of it as a control structure for pessimists.
Templates
Blade includes a few other helper methods to make your templates easier to construct and manage. It won’t write your views for you however, maybe we could add that to the task list for Laravel 5?
- php artisan project:complete
- Allow view composers to construct hair styles.
- Have views write themselves.
There we go. Until those features are in place, we will have to write our own templates. That doesn’t mean we have to put everything in one file though.
With PHP, you are able to include()
a file into the current file, executing its contents. You could do that with views to break them apart into separate files for organisational purposes. Laravel helps us achieve this goal by providing the @include()
Blade helper method to import one view into another, parsing its contents as a Blade template if required. Let’s have a look at an example of this in action.
Here’s header.blade.php
file containing the header for our page, and possibly even other pages.
<!-- app/views/header.blade.php -->
<h1>When does the Narwhal bacon?</h1>
Here’s the associated footer template.
<!-- app/views/footer.blade.php -->
<small>Information provided based on research as of 3rd May '13.</small>
Now here’s our primary template. The one that is being displayed by our routed Closure or Controller action.
<!-- app/views/example.blade.php -->
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Narwhals</title>
</head>
<body>
@include('header')
<p>Why, the Narhwal surely bacons at midnight, my good sir!</p>
@include('footer')
</body>
</html>
As you can see, the helper methods within the example.blade.php
template are pulling in the contents of our header and footer templates using the @include()
helper. Include takes the name of the view as a parameter, in the same short format as the View::make()
method that we used earlier. Let’s have a look at the resulting document.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Narwhals</title>
</head>
<body>
<h1>When does the Narwhal bacon?</h1>
<p>Why, the Narhwal surely bacons at midnight, my good sir!</p>
<small>Information provided based on research as of 3rd May '13.</small>
</body>
</html>
Our included templates have been... well, included into the page. This makes our header and footer templates reusable and DRY. We can include them into other pages to save repeating content, and to make that content editable in a single location. There is a better way of doing this though, so keep reading!
Template Inheritance
Laravel’s Blade provides a way to build templates that can benefit from inheritance. Many people find this confusing, yet it’s a really neat feature. I’m going to try and simplify it as best as I can and hopefully you will soon find the art of creating templates to be a pleasurable experience.
First of all let’s think about templates. There are some parts of a web page that don’t really change across each page. These are the tags that need to be present for any web page we view. We can call it our boilerplate code if you like. Here’s an example:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
</body>
</html>
We’re gonna use this layout for all of our pages. Why don’t we tell Laravel? Let’s say that it’s a Blade layout. To do that, we just need to define some areas that content can be inserted into. In Laravel we call these areas ‘sections’. This is how we define them:
<!-- app/views/layouts/base.blade.php -->
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
@section('head')
<link rel="stylesheet" href="style.css" />
@show
</head>
<body>
@yield('body')
</body>
</html>
Here we have created a template with two sections. Let’s look at the one within the body first, that’s the easy one. It looks like this:
@yield('body')
This statement tells blade to create a section here that we can fill in content for later. We give it the nickname ‘body’ so we can refer back to it later.
The other section looks like this:
@section('head')
<link rel="stylesheet" href="style.css" />
@show
This one is very similar to the ‘yield’ section, except that you can provide some default content. In the above example, the content between the @section
and @show
tags will be shown unless a child template chooses to override it.
So what do I mean by a child template? Well as always, let’s jump right in with an example.
<!-- app/views/home.blade.php -->
@extends('layouts.base')
@section('body')
<h1>Hurray!</h1>
<p>We have a template!</p>
@stop
Right, let’s walk through this. First we have the ‘extends’ blade function:
@extends('layouts.base')
This tells Blade which layout we will be using to render our content. The name that we pass to the function should look like those that you pass to View::make()
, so in this sithation we are referring to the ‘base.blade.php’ file in the ‘layouts’ directory within ‘app/views’. Remember that a period (.
) character represents a directory separator when dealing with views.
In Laravel 3 this function was called ‘@layout()’, but it has been renamed to bring it more inline with other templating engines such as Symfony’s twig. Beware, Laravel 3 devs!
Now that we know which layout we are using, it’s time to fill in the gaps. We can use the @section
blade function to inject content into sections within the parent template. It looks like this:
@section('body')
<h1>Hurray!</h1>
<p>We have a template!</p>
@stop
We pass the ‘@section’ function the nickname that we gave our section within the parent template. Remember? We called it ‘body’. Everything that is contained between ‘@section’ and ‘@stop’ will be injected into the parent template, where the ‘@yield(‘body’)’ is.
Let’s create a route to see this in action. To render the template, we need only add a View::make()
response to render the child template. Like this:
<?php
// app/routes.php
Route::get('/', function()
{
return View::make('home');
});
Now if we visit /
and view the source, we see that the page looks like this:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<h1>Hurray!</h1>
<p>We have a template!</p>
</body>
</html>
Okay, so the formatting might be a little different, but the content should be the same. Our section has been injected into our parent template. Since we didn’t override the contents of the ‘head’ section, the default value has been inserted.
So you see, we could have as many child templates as we want inheriting from this parent template. This saves us the effort of having to repeat the boilerplate code.
Let’s change the child template a little to provide some content for the ‘head’ section. Like this:
<!-- app/views/home.blade.php -->
@extends('layouts.base')
@section('head')
<link rel="stylesheet" href="another.css" />
@stop
@section('body')
<h1>Hurray!</h1>
<p>We have a template!</p>
@stop
As you can imagine, the head section has been injected with our additional CSS file, and the source for our page now looks like this:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href="another.css" />
</head>
<body>
<h1>Hurray!</h1>
<p>We have a template!</p>
</body>
</html>
Do you remember how the head section had some default content between the ‘@section’ and ‘@show’? Well, we might wish to append to this content, rather than replace it. To do this we can use the @parent
helper. Let’s modify our child template to use it, like this:
<!-- app/views/home.blade.php -->
@extends('layouts.base')
@section('head')
@parent
<link rel="stylesheet" href="another.css" />
@stop
@section('body')
<h1>Hurray!</h1>
<p>We have a template!</p>
@stop
The ‘@parent’ helper tells Blade to replace the parent marker, with the default content found within the parent’s section. That sentence might sound a little confusing, but it’s actually quite simple. Let’s have a look at how the source has changed for some clarity.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href="style.css" />
<link rel="stylesheet" href="another.css" />
</head>
<body>
<h1>Hurray!</h1>
<p>We have a template!</p>
</body>
</html>
See? Our ‘@parent’ marker was replaced with the default content from the parent’s section. You can use this method to append new menu entries, or extra asset files.
You can have as many chains of inheritance within blade templates as you like, the following example is perfectly fine.
<!-- app/views/first.blade.php -->
<p>First</p>
@yield('message')
@yield('final')
<!-- app/views/second.blade.php -->
@extends('first')
@section('message')
<p>Second</p>
@yield('message')
@stop
<!-- app/views/third.blade.php -->
@extends('second')
@section('message')
@parent
<p>Third</p>
@yield('message')
@stop
<!-- app/views/fourth.blade.php -->
@extends('third')
@section('message')
@parent
<p>Fourth</p>
@stop
@section('final')
<p>Fifth</p>
@stop
Woah crazy right! Try to follow the inheritance chain to see how the output is constructed. It might be best to work from the child templates upwards to each parent. If we were to render the ‘fourth’ view, this would be the outputted source.
<p>First</p>
<p>Second</p>
<p>Third</p>
<p>Fourth</p>
<p>Fifth</p>
To put it simply:
Fourth extends
Third which extends
Second which extends
First which is the base template.
You may also have noticed that the ‘final’ section of the base template had content provided by the fourth template file. This means you can provide content for a section from any ‘layer’. As you can see, Blade is very flexible.
Comments
As you probably know already, HTML has its own method of including comments. They look like this.
<!-- This is a lovely HTML comment. -->
You are right comment, you are lovely, but unfortunately, you also get outputted along with the rest of the page source. We don’t really want people reading the information that is meant for our developers.
Unlike HTML comments, PHP comments are stripped out when the page is pre-processed. This means that they won’t show up when you try to view source. We could include PHP comments in our view files like this:
<?php // This is a secret PHP comment. ?>
Sure, now our content is hidden. It’s a bit ugly though right? No room for ugliness in our utopian Blade templates. Let’s use a Blade comment instead, they compile directly to PHP comments.
{{-- This is a pretty, and secret Blade comment. --}}
Use blade comments when you want to put notes in your views that only the developers will see.
My books are available online for free to encourage learning. However, if you'd like for me to keep writing, then please consider buying a digital copy over at Leanpub.com.
It's available in PDF, ePub, and Kindle format, and contains a bunch of extras that you won't find on the site. I have a full-time job, and I write my books in my spare time. Please consider buying a copy so that I can continue to write new books from the comfort of my sofa!