Templates

Introduction

Templates is the simple, yet powerful templating engine that is included with Kiaan. Unlike some PHP templating engines, Template does not restrict you from using plain PHP code in your templates.

In fact, all templates are compiled into plain PHP code and cached until they are modified, meaning templates adds essentially zero overhead to your application. Templates template files use the .html file extension and are typically stored in the resources/views directory.

Templates views may be returned from routes or controllers using the global view helper.

Of course, as mentioned in the documentation on views data may be passed to the template view using the page helper's second argument:

Route::get('/', function () {
    return page('greeting', ['name' => 'Finn']);
});

Displaying Data

You may display data that is passed to your template views by wrapping the variable in curly braces.

For example, given the following route:

Route::get('/', function () {
    return page('welcome', ['name' => 'Ahmed']);
});

You may display the contents of the name variable like so:

Hello, {{ $name }}.

Template's {{ }} echo statements are automatically sent through PHP'shtmlspecialchars function to prevent XSS attacks.

You are not limited to displaying the contents of the variables passed to the view. You may also echo the results of any PHP function.

In fact, you can put any PHP code you wish inside of a templates echo statement:

The current UNIX timestamp is {{ time() }}.

Displaying Unescaped Data

By default, template{{ }} statements are automatically sent through PHP's htmlspecialchars function to prevent XSS attacks.

If you do not want your data to be escaped, you may use the following syntax:

Hello, {!! $name !!}.

Be very careful when echoing content that is supplied by users of your application.

You should typically use the escaped, double curly brace syntax to prevent XSS attacks when displaying user supplied data.

Template & JavaScript Frameworks

Since many JavaScript frameworks also use "curly" braces to indicate a given expression should be displayed in the browser, you may use the @ symbol to inform the template rendering engine an expression should remain untouched. For example:

<h1>Kiaan</h1>
 
Hello, @{{ name }}.

In this example, the @ symbol will be removed by template; however, {{ name }} expression will remain untouched by the template engine, allowing it to be rendered by your JavaScript framework.

The @ symbol may also be used to escape template directives:

{{-- Template --}}
@@if()
 a
<!-- HTML outphut -->
@if()

Rendering JSON

Sometimes you may pass an array to your view with the intention of rendering it as JSON in order to initialize a JavaScript variable. For example:

<script>
    var app = <?php echo json_encode($array); ?>;
</script>

The @escape Directive

If you are displaying JavaScript variables in a large portion of your template, you may wrap the HTML in the @escape directive so that you do not have to prefix each template echo statement with an @ symbol:

@escape
    <div class="container">
        Hello, {{ name }}.
    </div>
@endescape

Template Directives

In addition to template inheritance and displaying data, template also provides convenient shortcuts for common PHP control structures, such as conditional statements and loops. These shortcuts provide a very clean, terse way of working with PHP control structures while also remaining familiar to their PHP counterparts.

If Statements

You may construct if statements using the @if, @elseif, @else, and @endif directives. These directives function identically to their PHP counterparts:

@if (count($records) === 1)
    I have one record!
@elseif (count($records) > 1)
    I have multiple records!
@else
    I don't have any records!
@endif

For convenience, Template also provides an @unless directive:

@unless ($admin)
    You are not signed in.
@endunless

In addition to the conditional directives already discussed, the @isset and @empty directives may be used as convenient shortcuts for their respective PHP functions:

@isset($records)
    // $records is defined and is not null...
@endisset
 
@empty($records)
    // $records is "empty"...
@endempty

Section Directives

You may determine if a template inheritance section has content using the @hasSection directive:

@hasSection('navigation')
    <div class="pull-right">
        @content('navigation')
    </div>
 
    <div class="clearfix"></div>
@endif

Switch Statements

Switch statements can be constructed using the @switch, @case, @break, @default and @endswitch directives:

@switch($i)
    @case(1)
        First case...
        @break
 
    @case(2)
        Second case...
        @break
 
    @default
        Default case...
@endswitch

Loops

In addition to conditional statements, Template provides simple directives for working with PHP's loop structures. Again, each of these directives functions identically to their PHP counterparts:

@for ($i = 0; $i < 10; $i++)
    The current value is {{ $i }}
@endfor
 
@foreach ($users as $user)
    <p>This is user {{ $user->id }}</p>
@endforeach
 
@forelse ($users as $user)
    <li>{{ $user->name }}</li>
@empty
    <p>No users</p>
@endforelse
 
@while (true)
    <p>I'm looping forever.</p>
@endwhile

When using loops you may also skip the current iteration or end the loop using the @continue and @break directives:

@foreach ($users as $user)
    @if ($user->type == 1)
        @continue
    @endif
 
    <li>{{ $user->name }}</li>
 
    @if ($user->number == 5)
        @break
    @endif
@endforeach

You may also include the continuation or break condition within the directive declaration:

@foreach ($users as $user)
    @continue($user->type == 1)
 
    <li>{{ $user->name }}</li>
 
    @break($user->number == 5)
@endforeach

The Loop Variable

While iterating through a foreach loop, a $loop variable will be available inside of your loop. This variable provides access to some useful bits of information such as the current loop index and whether this is the first or last iteration through the loop:

@foreach ($users as $user)
    @if ($loop->first)
        This is the first iteration.
    @endif
 
    @if ($loop->last)
        This is the last iteration.
    @endif
 
    <p>This is user {{ $user->id }}</p>
@endforeach

If you are in a nested loop, you may access the parent loop's $loop variable via the parent property:

@foreach ($users as $user)
    @foreach ($user->posts as $post)
        @if ($loop->parent->first)
            This is the first iteration of the parent loop.
        @endif
    @endforeach
@endforeach

The $loop variable also contains a variety of other useful properties:

PropertyDescription

$loop->index

The index of the current loop iteration (starts at 0).

$loop->iteration

The current loop iteration (starts at 1).

$loop->remaining

The iterations remaining in the loop.

$loop->count

The total number of items in the array being iterated.

$loop->first

Whether this is the first iteration through the loop.

$loop->last

Whether this is the last iteration through the loop.

$loop->even

Whether this is an even iteration through the loop.

$loop->odd

Whether this is an odd iteration through the loop.

$loop->depth

The nesting level of the current loop.

$loop->parent

When in a nested loop, the parent's loop variable.

Including Subviews

Template's @include directive allows you to include a Template view from within another view. All variables that are available to the parent view will be made available to the included view:

<div>
    @include('shared.errors')
 
    <form>
        <!-- Form Contents -->
    </form>
</div>

Even though the included view will inherit all data available in the parent view, you may also pass an array of additional data that should be made available to the included view:

@include('view.name', ['status' => 'complete'])

If you attempt to @include a view which does not exist, Kiaan will throw an error. If you would like to include a view that may or may not be present, you should use the @includeIf directive:

@includeIf('view.name', ['status' => 'complete'])

If you would like to @include a view if a given boolean expression evaluates to true or false, you may use the @includeWhen and @includeUnless directives:

@includeWhen($boolean, 'view.name', ['status' => 'complete'])

@includeUnless($boolean, 'view.name', ['status' => 'complete'])

To include the first view that exists from a given array of views, you may use the includeFirst directive:

@includeFirst(['custom.admin', 'admin'], ['status' => 'complete'])

You should avoid using the __DIR__ and __FILE__ constants in your Template views, since they will refer to the location of the cached, compiled view.

Once

The @pushOnce and @prependOnce directives are available for your convenience:

@pushOnce('scripts')
    <script>
        // Your custom JavaScript...
    </script>
@endPushOnce

Raw PHP

In some situations, it's useful to embed PHP code into your views. You can use the Template @php directive to execute a block of plain PHP within your template:

@php
    $counter = 1;
@endphp

Comments

Template also allows you to define comments in your views. However, unlike HTML comments, template comments are not included in the HTML returned by your application:

{{-- This comment will not be present in the rendered HTML --}}

Building Layouts

Layouts Using Template Inheritance

Defining A Layout

Layouts may also be created via "template inheritance".

To get started, let's take a look at a simple example. First, we will examine a page layout. Since most web applications maintain the same general layout across various pages, it's convenient to define this layout as a single template view:

resources/views/layouts/app.html
<html>
    <head>
        <title>App Name - @section('title')</title>
    </head>
    <body>
        <div class="container">
            @section('container')
        </div>
    </body>
</html>

As you can see, this file contains typical HTML mark-up. However, take note of the @section and @content directives. The @content directive, as the name implies, defines a section of content, while the @section directive is used to display the contents of a given section.

Now that we have defined a layout for our application, let's define a child page that inherits the layout.

Extending A Layout

When defining a child view, use the @extends Template directive to specify which layout the child view should "inherit".

Views which extend a Template layout may inject content into the layout's sections using @content directives. Remember, as seen in the example above, the contents of these sections will be displayed in the layout using @section:

<!-- resources/views/child.html -->
@extends('layouts.app')
 
@content('title', 'Page Title')

@content('container')
    <p>This is my body content.</p>
@endcontent

In this example, the sidebar section is utilizing the @parent directive to append (rather than overwriting) content to the layout's sidebar. The @parent directive will be replaced by the content of the layout when the view is rendered.

Contrary to the previous example, this sidebar section ends with @endcontent instead of @show.

The @endcontent directive will only define a section while @show will define and immediately yield the section.

The @section directive also accepts a default value as its second parameter.

This value will be rendered if the section being yielded is undefined:

@section('content', 'Default content')

For shortness and more convenience, you can follow the following:

{{ -- Abreviation instead of "@content @endcontent" -- }}
@vSection('body')
    <p>This is my body content.</p>
@endVsection

Forms

CSRF Field

Anytime you define an HTML form in your application, you should include a hidden CSRF token field in the form so that the CSRF protection middleware can validate the request.

You may use the @csrf Template directive to generate the token field:

<form method="POST" action="/profile">
    @csrf
 
    ...
</form>

Method Field

Since HTML forms can't make PUT, PATCH, or DELETE requests, you will need to add a hidden _method field to spoof these HTTP verbs.

The @method directive can create this field for you:

<form action="/foo/bar" method="POST">
    @method('PUT')
 
    ...
</form>t

Blocks

Template allows you to push to named blocks which can be rendered somewhere else in another view or layout.

This can be particularly useful for specifying any JavaScript libraries required by your child views:

@push('scripts')
    <script src="/example.js"></script>
@endpush

You may push to a stack as many times as needed. To render the complete stack contents, pass the name of the stack to the @block directive:

<head>
    <!-- Head Contents -->
 
    @block('scripts')
</head>

If you would like to prepend content onto the beginning of a stack, you should use the @prepend directive:

@push('scripts')
    This will be second...
@endpush
 
// Later...
 
@prepend('scripts')
    This will be first...
@endprependml

For shortness and more convenience, you can follow the following:

@block('scripts')

{{ -- Abreviation instead of "@push @endpush" -- }}
@vBlock('scripts')
    This will be second...
@endVblock

{{ -- Abreviation instead of "@prepend @endprepend" -- }}
@pBlock('scripts')
    This will be second...
@endPblock

Fillters

You can use filters in strings.

{{ "Hello World!", 12 | limit }}

Last updated