Custom Laravel Blade Directive

Custom Laravel Blade Directive

Written by Tony Lea on Jun 20th, 2019 Views Report Post

Laravel Blade is a simple templating language which make views much easier to read. Blade gives us some simple shorthand syntax for common PHP functions such as @if, @foreach, @isset, and many others. Take a look at all the blade shorthand syntax at the official documentation page.

It's cool that we have all these shorthand functions to make our views look prettier. But wouldn't it be nice if we could create our own Blade Directives? That's what we'll cover in this tutorial.

Your First Custom Blade Directive

Creating your own Blade Directive is as easy as the following:

Blade::directive('directive_name', function () {
	return 'My First Blade Directive';
});

We will want to add this to our app/Providers/AppServiceProvider.php file:

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //   
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Blade::directive('directive_name', function () {
            return 'My First Blade Directive';
        });
    }
}

Keep in mind that you need to include the namespace to the Blade (use Illuminate\Support\Facades\Blade;) class in your AppServiceProvider.

Now, we can use our custom Blade Directive in any of our views.

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Custom Blade Directives</title>
    </head>
    <body>
        @directive_name()
    </body>
</html>

And if we load that view, we will see the page print out:

"My First Blade Directive"

and, just like that... You created your first custom blade directive. This was obviously a very simple example that just prints out a string, so let's move on to learning how you can add more functionality to your blade directives.

Adding Functionality to Blade Directives

You are probably reading this tutorial because you're interested in adding some useful functionality to your custom blade directive as opposed to just printing out a string...

In this section you will learn how to add functionality in your directive. Let's create a new blade directive called @isHome, which allows the view to detect if the user is viewing the homepage or a different route. Here is an example of what we want to accomplish.

@isHome
    <p>We are on the homepage</p>
@notHome
    <p>We are on a different page than the homepage</p>
@endHome

This can be accomplished by adding the following directives to our app/Providers/AppServiceProvider.php:

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //   
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Blade::directive('isHome', function () {
            $isHomePage = false;

            // check if we are on the homepage
            if ( request()->is('/') ) {
                $isHomePage = true;
            }

            return "<?php if ($isHomePage) { ?>";
        });

        Blade::directive('notHome', function () {
            return "<?php } else { ?>";
        });

        Blade::directive('endHome', function () {
            return "<?php } ?>";
        });
    }
}

Now if we have two routes. One that is the homepage and the other that is not.

Route::get('/', function () {
    return view('welcome');
});

Route::get('/posts', function(){
    return view('welcome');
});

We can use our blade syntax inside of the welcome.blade.php view to detect the homepage route.

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Adding Functionality to Custom Blade Directives</title>
    </head>
    <body>
        @isHome
            <p>We are on the homepage</p>
        @notHome
            <p>We are on a different page than the homepage</p>
        @endHome
    </body>
</html>

As you can see if we visit the home route, we will see the message, "We are on the homepage", otherwise if we visit the /posts route we will get the message "We are on a different page than the homepage".

Quick tip: After you create new directives you may need to clear your views by running:
php artisan view:clear

Pretty cool, right? Next, we will learn how you can use the Blade::if statement to make your directives even nicer and easier to work with.

Custom Blade "If" Directives

We can leverage the Laravel Blade If Directives to make our code from the previous example even nicer. Take a look at the following code:

Blade::if('isHome', function () {
    return request()->is('/');
});

Adding this to our app/Providers/AppServiceProvider.php file, would look like this:

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //   
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Blade::if('isHome', function () {
            return request()->is('/');
        });
    }
}

Then, inside of our view we need to change our blade syntax to look like the following:

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Custom Blade Directives</title>
    </head>
    <body>
        @isHome
            we are on home
        @else
            not home
        @endisHome
    </body>
</html>

And our code will function exactly the same as the previous example. Thanks to the new Laravel Blade If Directive (new to Laravel 5.5) our views and our directives are squeaky clean!

Passing an Argument to Blade Directives

Next, you may find it useful to pass arguments to your directives. In this quick example we will create a new blade directive called @greet, which will take in the name of the person you want to greet and echo it to the screen... Not very useful functionality, but this will show you how to pass an argument to your blade directive.

Take a look at the new app/Providers/AppServiceProvider.php file.

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //   
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Blade::directive('greet', function ($name) {
            return "<?php echo 'Hello ' . $name ?>";
        });
    }
}

You can see that our new directive will allow us to use the following blade syntax in any of our views:

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Custom Blade Directives</title>
    </head>
    <body>
        @greet('Tony')
    </body>
</html>

And we will get a nice greeting that says "Hello Tony". Pretty sweet, right?

Ok, what if you wanted to pass variables to your Blade If Directives? Let's see an example next.

Passing an Argument to Blade "If" Directives

This will perform very similar to the example above; however, I wanted to make sure that you were aware of the @elseif directive where you can check for different values. To illustrate this I will use an example from the Laravel documentation:

Take a look at the new directive inside of our AppServiceProvider:

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //   
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Blade::if('env', function ($environment) {
            return app()->environment($environment);
        });
    }
}

This directive will allow us to use the @env directive inside of our view to detect our current application environment:

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Custom Blade Directives</title>
    </head>
    <body>
        @env('local')
            <p>The application is in the local environment</p>
        @elseenv('testing')
            <p>The application is in the testing environment</p>
        @else
            <p>The application is not in the local or testing environment</p>
        @endenv
    </body>
</html>

You can see above that you can use the @elseenv blade directive to check for different environments.

Finally, I know what you may be thinking... If I have a bunch of Blade Directives my AppServiceProvider is going to get pretty messy. You would be right, that's why in the next section I will show you how you can create your own BladeDirectiveProvider.

Create a New Blade Service Provider

In order to keep things clean in our code we will probably want to create a separate file to store our Blade Directives. Run the following command to create a new service provider:

php artisan make:provider BladeServiceProvider

Now, you will see a new file located at app/Providers/BladeServiceProvider:

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;

class BladeServiceProvider extends ServiceProvider
{
    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }
}

You can now add your directives inside of the boot() method of your new BladeServiceProvider file. Before you can use your the directives in this file you will have to register the provider inside of the providers array in your app/config.php file like so:

'providers' => [

    // Other Service Providers
    App\Providers\BladeServiceProvider::class,
    
],

Conclusion

Creating custom blade directives for you application can make your views easier to read and write. It's a great way to add functionality you use over and over inside your views. 

Now, go forth! Create your custom blade directives!

Remember... If your directives do not seem to be working you need to run php artisan view:clear, it might save you some headaches.

Comments (0)