The Blade template engine is bundled with the Illuminate/View package. When working with the Themosis framework, you automatically get access to it in order to work out your views.
- Read Blade official documentation for more details about the template engine features.
In order to use the Blade engine, all your view files should use the .blade.php extension.
Here is an example of a basic view, using Blade, stored inside the theme views folder:
<!-- View stored in views/welcome.blade.php -->
@extends('layouts.main')
@section('main')
<h1>Hello, {{ $name }}</h1>
@endsection
@section('sidebar')
<h3>Latest posts</h3>
<ul>
@foreach($items as $item)
<li>{{ $item->post_title }}</li>
@endforeach
</ul>
@endsectionAnd this view may be returned to the browser like so:
Route::any('/', function ($post, $query) {
$posts = $query->get_posts();
return view('welcome', ['name' => 'Julien', 'items' => $posts]);
});In the previous example, we used the @extends syntax. This function allows you to use layouts:
<!-- Layout stored in views/layouts/main.blade.php -->
@include('header')
<div class="container">
@yield('main')
</div>
<div class="sidebar">
@section('sidebar')
<p>Sidebar section from the "main" layout file.</p>
@show
</div>
@include('footer')@include('header')This command can include a view file called header.php or header.blade.php.
@include('header', ['title' => 'Documentation'])Add the @section and @endsection statements to overwrite a layout section.
@extends('layouts.main')
@section('sidebar')
<p>New sidebar content</p>
@endsectionAdd the @@parent statement in order to keep the content of the parent section defined in the layout view.
@extends('layouts.main')
@section('sidebar')
@@parent
<p>Child sidebar content appended to parent's content</p>
@endsectionYou can create reusable views as well by leveraging the @component Blade directive. Here is an example of a reusable "alert" component:
<!-- /views/alert.blade.php -->
<div class="alert alert-danger">
{{ $slot }}
</div>The {{ $slot }} variable will contain the content you wish tin inject into the component. Now, in order to use this component, let's use the @component directive:
@component('alert')
<strong>Whoops!</strong> Something went wrong!
@endcomponentFor more information about the component directive, please read the Blade official documentation.
Hello {{ $name }}By default, the double curly braces echo the data and escape it.
Hello {!! $name !!}This is useful when you need to display HTML data like for example a post content.
By default, you could write the following statement:
{{ isset($name) ? $name : 'Default' }}Instead of writing a ternary statement, Blade allows you to use PHP's built in ?? "null coalesce" operator:
{{ $name ?? 'Default' }}@if(isset($value))
<p>The value is {{ $value }}.</p>
@elseif(is_array($value))
<p>The value is an array.</p>
@else
<p>Something is wrong, there is no value.</p>
@endifSometimes it is more readable to use @unless syntax instead of @if.
@unless(User::current()->can('edit_posts'))
<p>No editing permission.</p>
@endunlessThe above is the same as:
@if(!User::current()->can('edit_posts'))
<p>No editing permission.</p>
@endif<ul>
@for($i = 0; $i < 10; $i++)
<li>Item {{ $i }}</li>
@endfor
</ul>@while(true)
<p>Show it!</p>
@endwhile@foreach($items as $key => $value)
<p>This {{ $value }} opens that {{ $key }}.</p>
@endforeachCheck the official documentation for information about the
$loopvariable.
If you need to display a string that is wrapped in curly braces, you may escape the Blade behavior by prefixing your text with an @ symbol:
@{{ This is not processed by Scout }}Check also the verbatim directive for larger text.
{{-- This comment will not be rendered in HTML --}}Since several JavaScript frameworks use curly braces to indicate expressions to be displayed in the browser, you may use the @ symbol to inform the Blade engine to not modify the expression:
Hello, @{{ name }}.The above example will render the following text in your HTML so javascript can capture it for rendering:
Hello, {{ name }}.If you are displaying JavaScript variables in a large portion of your template, you may wrap the HTML in the @verbatim directive so that you do not have to prefix each Blade echo statement with an @ symbol:
@verbatim
<div class="container">
Hello, {{ name }}.
</div>
@endverbatimBlade allows you to push to named stacks which can be rendered somewhere else in another view or layout:
@push('scripts')
<script src="/example.js"></script>
@endpushYou may push to a stack as many times as needed. To render the complete stack contents, pass the name of the stack to the @stack directive:
<head>
<!-- Head Contents -->
@stack('scripts')
</head>More information about stacks on the official Blade documentation.
The @inject directive may be used to retrieve a service from the service container. The first argument passed to @inject is the name of the variable the service will be placed into, while the second argument is the class or interface name of the service you wish to resolve:
@inject('metrics', 'App\Services\MetricsService')
<div>
Monthly Revenue: {{ $metrics->monthlyRevenue() }}.
</div>Blade allows you to add new compiler statements, called directives by using the directive() method. The Themosis framework now provides the Blade facade so it is easier to extend the template engine for your application.
Here is an example where we create a @menu Blade directive in order to render a WordPress menu:
public function boot()
{
Blade::directive('menu', function ($expression) {
return '<?php wp_nav_menu('.$expression.'); ?>';
});
}We recommend you to register directives from a service provider boot method.
The Themosis framework provides extra directives to help you work with WordPress templates.
The @loop directive gives you a shortcut to handle the WordPress loop.
In place of typing these statements:
<?php
if (have_posts()) {
while (have_posts()) {
the_post();
?>
<h1><?php the_title(); ?></h1>
<div>
<?php the_content(); ?>
</div>
<?php
}
}Simply write this code into your view:
@loop
<h1>{{ Loop::title() }}</h1>
<div>
{{ Loop::content() }}
</div>
@endloopThe @query directive provides a shortcut to run custom WordPress loops:
@query(['post_type' => 'post', 'posts_per_page' => 3])
<h1>{{ Loop::title() }}</h1>
<div>
{{ Loop::content() }}
</div>
@endqueryThe array you pass inside the @query statement is equivalent to the one you pass when using the WP_Query class. Check the WordPress reference to customize your loop query. You can also pass the WP_Query instance to the @query statement.
The
Loopclass used in the examples is a core class to be used only inside the WordPress loop. More information below.
The @wp_head directive is a shortcut for <?php wp_head(); ?>:
<head>
@wp_head
</head>
<body>The following directives also work as alias:
@head@wphead
The @wp_footer directive is a shortcut for <?php wp_footer(); ?>
@wp_footer
</body>The following directives also work as alias:
@footer@wpfooter
The @template directive is a mechanism similar to the get_template_part() function for Blade views:
@template('parts.content', get_post_type())The above example will try to load the following views: parts.content-products or parts.content-page or parts.content-post...
If the directive was not able to find one of those "composed" views, it will try to fetch the default parts.content view passed as the first argument.
The Loop helper class provides methods with a simple syntax in order to call WordPress loop functions.
Here is a list of the available methods.
This class only works inside WordPress loop statements. The
Loopclass methods always return a result, so use echo statements to output their content.
@loop
$id = Loop::id();
@endloopThis method accepts one argument:
- $post: int|WP_Post The post ID or WP_Post instance
@loop
<h1>{{ Loop::title() }}</h1>
@endloop@loop
<em>{{ Loop::author() }}</em>
@endloop- $field: string The author meta name
- $user_id: int The author ID
@loop
<em>{{ Loop::authorMeta('email') }}</em>
@endloop- $more_text: string The more text appended to the excerpt
- $strip_teaser: bool Strip teaser content before the more text
@loop
<article>{{ Loop::content() }}</article>
@endloop- $post: int|WP_Post The post ID or instance
@loop
<aside>{{ Loop::excerpt() }}</aside>
@endloopThis method accepts two arguments:
- $size: string|array The size of the thumbnail
- $attr: string|array The img tag attributes
- $post: int|WP_Post The post ID or instance
@loop
{{ Loop::thumbnail('thumbnail') }}
@endloop- $size: string The image size
- $icon: bool Use media icon
@loop
<img src="{{ Loop::thumbnailUrl('thumbnail') }}">
@endloop- $post: int|WP_Post The post ID or instance
- $leavename: bool Keep or not the post name.
@loop
<a href="{{ Loop::link() }}">Read more</a>
@endloop- $id: int The post ID
@loop
<ul>
@foreach(Loop::category() as $cat)
<li>{{ $cat->name }}</li>
@endforeach
</ul>
@endloop- $id: int The post ID
@loop
<ul>
@foreach(Loop::tags() as $tag)
<li>{{ $tag->name }}</li>
@endforeach
</ul>
@endloopPass the custom taxonomy slug as first argument.
- $taxonomy: string The taxonomy slug
- $post: int|WP_Post The post ID or instance
@loop
<ul>
@foreach(Loop::terms('custom-slug') as $term)
<li>{{ $term->name }}</li>
@endforeach
</ul>
@endloop- $d: string The date format
- $post: int|WP_Post The post ID or instance
@loop
<time>{{ Loop::date() }}</time>
@endloopThe Loop::postClass() method returns the HTML class attribute with WordPress generated class terms. You also have the opportunity to add one or more custom classes to the current post or a defined post.
Loop::postClass($class = '', $post_id = null):
- $class: string|array One or more classes to add.
- $post_id: int|WP_Post Given post ID or post object.
Output the post classes:
@loop
<article {{ Loop::postClass() }}>
<h2>Title</h2>
</article>
@endloopHere is an example of the rendered HTML code with the class attribute:
<article class="post-4 post type-post status-publish hentry">
<h2>Title</h2>
</article>Note that this function is heavy and may slow your pages if used during the output of a list of posts.
- $label: string Link content
- $max_page: int Max pages in current query
@loop
{!! Loop::nextPage() !!}
@endloop- $label: string Link content
@loop
{!! Loop::previousPage() !!}
@endloop- $args: string|array Paginate links arguments
@loop
{!! Loop::paginate() !!}
@endloopBy default, Poedit cannot find strings to translate from Blade templates. Here is a list of parameters to add to your Poedit software preferences, so it can detect translation strings from your Blade views:
- Open Poedit
- Go to Preferences -> Parsers
- Add a new parser with following settings:
- Language:
Blade - Extension:
*.blade.php - Parser command:
xgettext --language=Python --add-comments=TRANSLATORS --force-po -o %o %C %K %F - An item in keyword list:
-k%k - An item in input files list:
%f - Source code charset:
--from-code=%c
- Language:
- Click save
In order for this to work, you must have a poedit project correctly setup pointing to the languages folder of either your theme or custom plugin and define the gettext methods and resources base path. From the catalog preferences, set the sources paths like so:
- Base path:
../ - Paths:
incviews
as well as adding the following gettext methods to the source keywords catalog tab:
___e_n:1,2_x:1,2c_ex:1,2c_nx:4c,1,2esc_attr__esc_attr_eesc_attr_x:1,2cesc_html__esc_html_eesc_html_x:1,2c_n_noop:1,2_nx_noop:3c,1,2__ngettext_noop:1,2