Complete Guide To blade Templating in laravel 5.2

IN this tutorial you learn how blade templating works in laravel 5.2 from scratch . This tutorial is best for beginners as well as for developers . Compared to most other backend languages, PHP actually functions relatively well as a templating language. But it has its shortcomings, and it’s also just ugly to be be using <?php inline all over the place, so you can expect most modern frameworks to offer a templating language.

Unlike many other Symfony-based frameworks, Laravel doesn’t use Twig by default—although there’s a Twig Bridge package that makes it easy to use Twig if you like it.

Instead, Laravel provides a custom templating engine called Blade, which is inspired by .NET’s Razor engine. It’s functionally very similar to Twig, but the syntax is closer to Razor and the learning curve for PHP developers tends to be lower than for Twig.

Take a look at a common display pattern in PHP, Twig, and Blade below

PHP vs. Twig vs. Blade
<?php /* PHP */ ?> <?php if (empty($users)): ?>     No users. <?php else: ?>     <?php foreach ($users as $user): ?> <?= $user->first_name ?> <?= $user->last_name ?><br>     <?php endforeach; ?> <?php endif; ?>
{# Twig #} {% for user in users %} {{ user.first_name }} {{ user.last_name }}<br> {% else %}     No users. {% endfor %}
{{-- Blade --}} @forelse ($users as $user)  {{ $user->first_name }} {{ $user->last_name }}<br> @empty No users. @endforelse

As you can see, Blade’s syntax tends to be somewhere between PHP and Twig—it’s more powerful, like Twig, and has convenience helpers like forelse, but its syntax is closer to PHP than Twig.

Additionally, since all Blade syntax is compiled into normal PHP code and then cached, it’s fast and it allows you to use native PHP in your Blade files if you want. The common recommendation, however, is to keep any PHP tags out of your Blade files.

Control structures

Most of the control structures in Blade will be very familiar. Many directly echo the name and structure of the same tag in PHP.

There are a few convenience helpers, but in general, the control structures primarily just look cleaner than they would in PHP.

Conditionals

@if

Blade’s @if ($condition) compiles to <?php if ($condition): ?>. @else, @elseif, and @endif also compile to the exact same syntax in PHP. Take a look below for an example.

@if, @else, @elseif, and @endif
@if (count($talks) === 1) There is one talk at this time period. @elseif (count($talks) === 0) There are no talks at this time period. @else There are {{ count($talks) }} talks at this time period. @endif

Just like with the native PHP conditionals, you can mix and match these how you want. They don’t have any special logic; there’s literally a parser looking for something with the shape of @if ($condition) and replacing it with the appropriate PHP code.

@unless and @endunless

@unless, on the other hand, is a new syntax that doesn’t have a direct cognate in PHP. It’s the exactly the same as @if, but the inverse. @unless ($condition) is the same as <?php if (! $condition). See it in use in below code snippet

@unless and @endunless
@unless ($user->hasPaid()) You can complete your payment by switching to the payment tab. @endunless

Loops

@for, @foreach, and @while

@for, @foreach, and @while work the same in Blade as they do in PHP.

@for and @endfor
@for ($i = 0; $i < $talk->slotsCount(); $i++) The number is {{ $i }} @endfor
Example 4-6. @foreach and @endforeach
@foreach ($talks as $talk)  {{ $talk->title }} ({{ $talk->length }} minutes) @endforeach
@while
@while ($item = array_pop($items)) {{ $item->orSomething() }}<br> @endwhile

@forelse

We’ve already looked at it in the introduction, but @forelse is a @foreach that also allows you to program in a fallback if the object you’re iterating over is empty.

@forelse
@forelse ($talks as $talk)  {{ $talk->title }} ({{ $talk->length }} minutes) @empty No talks this day. @endforelse

Or

If you’re ever unsure whether a variable is set, you’re probably used to checking isset() on it before echoing it, and echoing something else if it’s not set. Blade has a convenience helper, or, that does it for you and lets you set a default fallback: {{ $title or "Default" }} will echo the value of $title if it’s set, or “Default” if not.

Template inheritance

Just like Twig, Blade provides a structure for inheritance that allows views to extend, modify, and include other views.

Here’s how inheritance is structured with Blade.

Defining sections with @section/@show and @yield

Let’s start with a top-level Blade layout, like in code snippet below . This is the definition of the generic page wrapper that we’ll later place page-specific content into.

Example 4-9. Blade layout
<!-- resources/views/layouts/master.blade.php --> <html> <head> <title>My Site | @yield('title', 'Home Page')</title> </head> <body> <div class="container"> @yield('content') </div> @section('footerScripts') <script src="app.js"> @show </body> </html>

This looks a bit like a normal HTML page, but you can see we’ve yielded in two places (title and content), and we’ve defined a section in a third (footerScripts).

We have three Blade directives here that each look a little different: yield(content) alone, yield(title, \'Home Page\) with a defined default, and @section … @show with actual content in it.

All three function essentially the same. All three are defining that there’s a section with a given name (which is the first parameter). All three are defining that the section can be extended later. And all three are telling what to do if the section isn’t extended, either by providing a string fallback (Home Page), no fallback (which will just not show anything if it’s not extended), or an entire block fallback (in this case, <script src="app.js">).

What’s different? Well, clearly, yield(content) has no default content. But additionally, the default content in yield(title) only will be shown if it’s never extended. If it is extended, its child sections will not have programmatic access to the default value. @section … @show, on the otherhand, is both defining a default and doing so in a way that its default contents will be available to its children, through @parent.

Once you have a parent layout like this, you can extend it like below.

Extending a Blade Layout
<!-- resources/views/dashboard.blade.php --> @extends('layouts.master') @section('title', 'Dashboard') @section('content') Welcome to your application dashboard! @endsection @section('footerScripts') @parent <script src="dashboard.js"> @endsection

This child view will actually allow us to cover a few new concepts in Blade inheritance.

@extends

First, with @extends('layouts.master'), we define that this view should not be rendered on its own, but that it instead extends another view. That means its role is to define the content of various sections, but not to stand alone. It’s almost more like a series of buckets of content, rather than an HTML page. It also defines that the view it’s extending lives at resources/views/layouts/master.blade.php.

@section and @endsection

Second, with @section('title', 'Dashboard'), we provide our content for the first section, title. Since the content is so short, instead of using @section and @endsection, we’re just using a shortcut. This allows us to pass the content in as the second parameter of @section and then move on. If it’s a bit disconcerting to see @section without @endsection, you could just use the normal syntax.

Third, with @section('content') and on, we use the normal syntax to define the contents of the content section. We’ll just throw a little greeting in for now. Note, however, that when you’re using @section in a child view, you end it with @endsection (or its alias @stop), instead of @show, which is reserved for defining sections in parent views.

@parent

Fourth, with @section('footerScripts') and on, we use the normal syntax to define the contents of the footerScripts section.

But remember, we actually defined that content (or, at least, its “default”) already in the master layout. So this time, we have two options: we can either overwrite the content from the parent view, or we can add to it.

You can see that we have the option to include the content from the parent by using the @parent directive within the section. If we didn’t, the content of this section would entirely overwrite anything defined in the parent for this section.

@include

So, we have the basics of inheritance established. There are a few more tricks we can perform.

What if we’re in a view and want to pull in another view? Maybe we have a call-to-action “Sign up” button that we want to re-use around the site. And maybe we want to customize its button text every time we use it. Take a look below

Including view partials with @include
<!-- resources/views/home.blade.php --> <div class="content" data-page-name="{{ $pageName }}"> <p>Here's why you should sign up for our service: <strong>It's Great.</strong></p> @include('sign-up-button', ['text' => 'See just how great it is']) </div> <!-- resources/views/sign-up-button.blade.php --> <a class="button button--callout" data-page-name="{{ $pageName }}"> <i class="exclamation-icon"></i> {{ $text }} </a>

@include pulls in the partial and, optionally, passes data into it. Note that, not only can you explicitly pass data via the second parameter of @include, you can also reference any variables that are available to the including view ($pageName, in this example). Once again, you can do whatever you want, but I would recommend you consider always passing every variable explicitly that you intend to use, just for clarity.

@each

You can probably imagine some circumstances in which you’d need to loop over an array or collection and @include a partial for each item. There’s a directive for that.

Let’s say we have a sidebar composed of modules, and we want to incude multiple modules, each with a different title. Take a look at code below

Using view partials in a loop with @each
<!-- resources/views/sidebar.blade.php --> <div class="sidebar"> @each('partials.module', $modules, 'module', 'partials.empty-module') </div> <!-- resources/views/partials/module.blade.php --> <div class="sidebar-module"> <h1>{{ $module->title }}</h1> </div> <!-- resources/views/partials/module.blade.php --> <div class="sidebar-module"> No modules :( </div>

Take a look at that @each syntax. The first parameter is the name of the view partial. The second is the array or collection to iterate over. The third is the variable name that each item will be passed to the view as. And the optional fourth parameter is the view to show if the array or collection is empty.

View composers and service injection

we can pass data to our views from the route definition . the example is below

Reminder on how to pass data to views
Route::get('passing-data-to-views', function () { return view('dashboard') ->with('key', 'value'); });

There are times, however, when you will find yourself passing the same data over and over to multiple views. Or, you might find yourself using a header partial or something else similar that requires some data; will you now have to pass that data in from every route definition that might ever load that header partial?

Binding data to views using view composers

Thankfully, there’s a simpler way. The solution is called a view composer, and it allows you to define that any time a particular view loads, it should have certain data passed to it–without the route definition having to pass that data in explicitly.

Let’s say you have a sidebar on every page which is defined in a partial named partials.sidebar and then included on every page. This sidebar shows a list of the last seven posts that were published on your site. If it’s on every page, every route definition would normally have to grab that list and pass it in,

Passing sidebar data in from every route
Route::get('home', function () { return view('home') ->with('posts', Post::recent()); }); Route::get('about', function () { return view('about') ->with('posts', Post::recent()); });

That could get annoying quickly. Instead, we’re going to use view composers to “share” that variable with a prescribed set of views. We can do this a few ways, so let’s start simple and move up.

Sharing a variable globally

First, the simplest: Just globally “share” a variable like in code snippet below

Example 4-15. Sharing a variable globally
view()->share('posts', Post::recent());

You’ll likely place this code in some form of custom ViewComposerServiceProvider (see [Link to Come] to learn more about Service Providers), but for now you could also just put it in App\Providers\AppServiceProvider in the boot method.

Using view()→share() makes the variable accessible to every view in the entire application, however, so it might be overkill.

Closure-based view composers

The next option is to use a Closure-based view composer to share variables with a single view like below

Creating a Closure-based view composer
view()->composer('partials.sidebar', function ($view) { $view->with('posts', Post::recent()); });

As you can see, we’ve defined the name of the view we want it shared with (partials.sidebar) in the first parameter and then passed a Closure to the second parameter; in the Closure, we’ve used $view→with() to share a variable, but now only with a specific view.

View composers for multiple views

Anywhere a view composer is binding to a particular view ( see code snippet above ) which binds to partials.sidebar), you can also pass an array of view names instead to bind to multiple views.

Or, you can use an asterisk in the view path: partials.*, or tasks.*, or just *.

Class-based view composers

Finally, the most flexible but also most complex option is to create a dedicated class for your view composer.

First, let’s create the view composer class. There’s no formally defined place for view composers to live, but the docs recommend App\Http\ViewComposers. So let’s create App\Http\ViewComposers\RecentPostsComposer like below

A view composer
<?php namespace App\Http\ViewComposers; use App\Post; use Illuminate\Contracts\View\View; class RecentPostsComposer { private $posts; public function __construct(Post $posts) { $this->posts = $posts; } public function compose(View $view) { $view->with('posts', $this->posts->recent()); } }

As you can see, we’re injecting the Post model (type-hinted constructor parameters of view composers will be automatically injected; see [Link to Come] for more on the container and dependency injection). Note that we could skip the private $posts and the constructor injection and just used Post::recent() in the compose method if we wanted. Then when this composer is called, it runs the compose method, in which we bind the posts variable to the result of the recent() method.

Just like the other methods of sharing variables, this view composer needs to have a binding somewhere. Again, you’d likely create a custom ViewComposerServiceProvider, but for now we’ll just put it in the boot method of App\Providers\AppServiceProvider.

Registering a view composer in AppServiceProvider
view()->composer( 'partials.sidebar', 'App\Http\ViewComposers\RecentPostsComposer' );

Note that this binding is the same as a Closure-based view composer, but instead of passing a Closure, we’re passing the class name of our view composer. Now, every time Blade renders the partials.sidebar view, it’ll automatically run our provider and pass the view a posts variable set to the results of the recent() method on our Post model.

Service injection

There are three primary types of data we’re most likely to inject into a view: collections of data to iterate over, single objects that you’re displaying on the page, and services that generate data or views.

With a service, the pattern will most likely look like athe code below, where we inject an instance of the service into the route definition by type-hinting it in the route definition’s method signature, and then pass it into the view.

Example 4-19. Injecting services into a view via the route definition constructor
Route::get('injecting', function (AnalyticsService $analytics) { return view('injecting') ->with('analytics', $analytics); });

Just as view composers, Blade’s service injection offers a convenient shortcut to reducing duplication in your route definitions. Normally the content of a view using the navigation service above might look like in code below

Using an injected navigation service in a view
<div class="finances-display"> {{ $analytics->getBalance() }} / {{ $analytics->getBudget() }} </div>

Blade service injection makes it easy to inject an instance of a class out of the container directly from the view, like in snippet below

Injecting a service directly into a view
@inject('analytics', 'App\Services\Analytics') <div class="finances-display"> {{ $analytics->getBalance() }} / {{ $analytics->getBudget() }} </div>

As you can see, this @inject method has actually made an $analytics variable available, which we’re using later in our view.

The first parameter of @inject is the name of the variable you’re injecting, and the second parameter is the class or interface that you want to inject an instance of. This is resolved just like when you type-hint a dependency in a constructor elsewhere in Laravel, and if you’re unfamiliar with how that works, take a look at [Link to Come] to learn more.

Just like view composers, Blade service injection makes it easy to make certain data or functionality available to every instance of a view, without having to inject it via the route definition every time.

Custom Blade directives

All of the built-in syntax of Blade that we’ve covered so far—@if, @unless, etc.–are called Blade directives. Each Blade directive is a mapping between a pattern (e.g. @if ($condition)) and a PHP output (e.g. <?php if ($condition): ?>).

Directives aren’t just for the core; you can actually create your own. You might think directives are good for making little shortcuts to bigger pieces of code—for example, @button('buttonName'), and having it expand to a larger set of button HTML. This isn’t a terrible idea, but for simple code expansion like this you might be better off including a view partial.

I’ve found custom directives the most useful when they simplify some form of repeated logic. Let’s say we were tired of having to wrap our code with @if (Auth::guest()) (to check if a user is logged in or not) and we wanted a custom @ifGuest directive.

As with view composers, it might be worth having a custom Service Provider to register these, but for now let’s just put it in the boot method of App\Providers\AppServiceProvider. Take a look at code snippet below to see what this binding will look like.

Binding a custom Blade directive
// AppServiceProvider public function boot() { Blade::directive('isGuest', function () { return "<?php if (Auth::guest()): ?>"; }); }

We’ve now registered a custom directive @isGuest, which will be replaced with the PHP code <?php if (Auth::guest()): ?>.

This might feel strange. You’re writing a string that will be returned and then executed as PHP. It takes a minute to get your brain wrapped around it, but once you do you can see how powerful it can be.

Warning

You might be tempted to do some logic to make your custom directive faster by performing an operation in the binding and then embedding the result within the returned string:

Blade::directive('isGuest', function () { // Anti-pattern! Do not copy. $isGuest = Auth::guest(); return "<?php if ({$isGuest}): ?>"; });

The problem with this idea is that it assumes this directive will be re-created on every page load. However, Blade caches aggressively, so you’re going to find yourself in a bad spot if you try this.

Parameters in custom Blade directives

What if you want to check a condition in your custom logic? Check out code

Example 4-23. Creating a Blade directive with parameters
// Binding Blade::directive('newlinesToBr', function ($expression) { return "<?php echo nl2br{$expression}; ?>"; }); // In use <p>@newlinesToBr($message->body)</p>

The $expression parameter received by the Closure represents whatever’s within the parentheses and the parentheses themselves. So, in snippet above $expression is actually ($message→body). That’s why there are no parentheses after nl2br in the binding; they’re already included with $expression.

So, if you find yourself constantly writing the same conditional logic over and over, consider a Blade directive.

Testing

Testing views is not common, but it’s possible. The most common method of testing views is through application testing, meaning that you’re actually calling the route that displays the views, and ensuring the views have certain content. You can also click buttons or submit forms and ensure that you are redirected to a certain page, or that you see a certain error. Learn more in [Link to Come].

Testing that a view displays certain content
// EventsTest.php public function test_list_page_shows_all_events() { $event1 = factory(Event::class)->create(); $event2 = factory(Event::class)->create(); $this->visit('events') ->andSee($event1->title) ->andSee($event2->title); }

TL;DR

Blade is Laravel’s templating engine. It’s a little bit like Twig and a little bit like straight PHP. Its “safe echo” brackets are {{ and }}, its unprotected echo brackets are {!! and !!}, and it has a series of directives that all begin with @ (@if and @unless, for example).

Define a parent template and leave “holes” in it for content using @yield and @section/@show. Teach its child views to extend it using @extends('parent.view.name'), and define their sections using @section/@endsection. Use @parent to reference the content of the same block in the parent.

View composers make it easy to define that, every time a particular view or subview loads, it has certain information available to it. And service injection allows the view itself to dictate what data it needs.

Deven Rathore

Deven is an Entrepreneur, and Full-stack developer, Constantly learning and experiencing new things. He currently runs CodeSource.io and Dunebook.com.

Published by
Deven Rathore

Recent Posts

Flutter App Development: Essential Things You Should Know

Divided by mobile operating systems, companies have to develop their apps twice and roll them…

10 hours ago

7 Tips To Build Responsive & Dynamic Drupal Website For Your Business

For optimal user experience, consumers want responsive websites that are easy to use, multi-device friendly,…

2 days ago

OpenCart vs Magento: What You Should Choose in 2021

Users all over the world are faced with the problem of choosing a platform for…

1 week ago

Top 20 Android Open Source Projects

Reading codes and contributing to open source has been proven to be one of the…

3 weeks ago

Top 5 tools to proofread and edit essays with the help of software

Poor grammar and incorrect spelling can significantly lower the value of any literary work. Going…

9 hours ago

The Best 5 Career Advice for Web Design Students

Are you thinking of a career in web design but not sure where to start? The…

4 weeks ago