Support the ongoing development of Laravel.io →

Boost Your Laravel Templates with Custom Blade Directives

11 Apr, 2023 5 min read

Photo by Theme Photos on Unsplash

Introduction

Blade is a powerful templating engine that you can use in Laravel. It allows you to write clean templates using simple and understandable syntax to build some pretty complex layouts.

One of the cool features that I like about Blade is the ability to create your own custom directives. They allow you to define your own custom syntax that you can use in your Blade templates to make them more expressive and easier to read.

In this article, we'll take a look at how to create your own custom Blade directives in Laravel.

What are Blade Directives?

Blade directives are handy little shortcuts that you can add to your templates to reduce the need of using raw PHP. They start with the @ symbol, followed by the directive and any arguments.

If you've used Laravel before, you'll have likely interacted with Blade directives without realising. For example, you may have written an if statement in your Blade template using the @if and @endif directives like so:

@if($user->isAdmin())
    <p>This user is an admin.</p>
@endif

When the Blade template is converted to regular PHP, it will be converted to this:

{!! <?php if($user->isAdmin()): ?>
    <p>This user is an admin.</p>
{!! <?php !!} endif; ?>

As you can see, although the raw PHP version isn't quite as elegant, it's still pretty easy to read.

So, to show the amount of complexity that Blade hides from us, let's take a look at another seemingly simple directive that has quite a lot going on behind the scenes.

You may have used the @foreach and @endforeach directives to loop through a collection of items:

@foreach($users as $user)
    <p>{{ $user->name }}</p>
@endforeach

When this Blade template is converted to regular PHP, it will be converted to this:

{!! <?php $__currentLoopData = $users; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $user): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
    <p>{!! <?php echo e($user->name); ?></p>
{!! <?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?>

As you can see, there's a lot more going on here that Blade tidies away nicely for us.

Laravel comes with many built-in Blade directives, which you can check out in the documentation. For a large majority of your projects' needs, these directives will likely provide all the functionality you need.

But there may be times when you want to create your own custom Blade directives. You might want to do this if you find yourself writing the same small pieces of code over and over again. So it can be a nice way to simplify your templates and make them more expressive.

However, it's worth noting that if the code you keep rewriting is more than a few lines long, you might want to consider moving it into a component instead. Directives are best suited for short pieces of code (maybe one or two PHP statements).

Creating Custom Blade Directives

Let's take a quick look at how you can write your own custom Blade directives.

We'll imagine that we want to write a custom directive that renders a Carbon date object in a specific human-friendly format. We'll call this directive @friendlyDateTime.

Before we try creating the new directive, let's take a look at how we would write the code to render a Carbon date object in the format we want without using a custom directive. We might do something like this:

$carbonObject = \Carbon\Carbon::parse('2023-03-24 14:30:00');

echo $carbonObject->format('D d M Y @ H:i');

Running the above code would output the following:

Fri 24 Mar 2023 @ 14:30

Now let's convert this code to a Blade directive. To do this, we'll need to register the directive with the Blade compiler. We can do this by using the Blade::directive method in a service provider. For the purpose of this article, we're going to use the existing AppServiceProvider, but you may wish to add this code to a new service provider if you prefer.

Let's take a look at the code where we've registered the directive:

namespace App\Providers;

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

class AppServiceProvider extends ServiceProvider
{
    // ...

    public function boot()
    {
        Blade::directive('friendlyDateTime', function (string $expression): string {
            return "{!! <?php echo ($expression)->format('D d M Y @ H:i'); ?>";
        });
    }
}

As we can see in the code above, we've defined a new @friendlyDateTime directive that accepts a string, such as $user->created_at. When the Blade templates are compiled into plain PHP code, it will look something like this:

{!! <?php echo ($user->created_at)->format('D d M Y @ H:i'); ?>

In our Blade templates, we should be able to use the @friendlyDateTime directive. Here are a few examples of how you may want to use it:

@friendlyDateTime(\Carbon\Carbon::parse('2023-03-24 14:30:00'))

@friendlyDateTime(now())

@friendlyDateTime($user->created_at)

@friendlyDateTime($post->updated_at)

@friendlyDateTime($user->last_login_at)

As you can see, it's relatively simple to create your own custom Blade directives. You may also want to add more complex logic to these directives. For example, you may decide to add the ability for your application's users to choose the date format they see (which we'll assume is stored in a datetime_format field on the users table).

So, you could change your Blade directive code like so:

Blade::directive('friendlyDateTime', function (string $expression): string {
    return "{!! <?php echo ($expression)->format(auth()->datetime_format); ?>";
});

If we were to imagine that some users would prefer to see "Fri Mar 24 2023 @ 14:30" rather than "Fri 24 Mar 2023 @ 14:30", this directive would handle this without us needing to add any conditional logic to our templates.

Conclusion

Hopefully, this article should have given you a quick insight into what Blade directives are, how they work, and how to create your own.

If you enjoyed reading this post, I'd love to hear about it. Likewise, if you have any feedback to improve the future ones, I'd also love to hear that too.

You might also be interested in checking out my 220+ page ebook "Battle Ready Laravel" which covers similar topics in more depth.

If you're interested in getting updated each time I publish a new post, feel free to sign up for my newsletter below.

Keep on building awesome stuff! 🚀

Last updated 2 weeks ago.

driesvints, zamon, achmedislamic, massimoselvi liked this article

4
Like this article? Let the author know and give them a clap!
ash-jc-allen (Ash Allen) I'm a freelance Laravel web developer from Preston, UK. I maintain the Ash Allen Design blog and get to work on loads of cool and exciting projects 🚀

Other articles you might like

November 18th 2024

Laravel Custom Query Builders Over Scopes

Hello 👋 Alright, let's talk about Query Scopes. They're awesome, they make queries much easier to r...

Read article
November 19th 2024

Access Laravel before and after running Pest tests

How to access the Laravel ecosystem by simulating the beforeAll and afterAll methods in a Pest test....

Read article
November 11th 2024

🍣 Sushi — Your Eloquent model driver for other data sources

In Laravel projects, we usually store data in databases, create tables, and run migrations. But not...

Read article

We'd like to thank these amazing companies for supporting us

Your logo here?

Laravel.io

The Laravel portal for problem solving, knowledge sharing and community building.

© 2024 Laravel.io - All rights reserved.