Boost Your Laravel Templates with Custom Blade Directives
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! 🚀
driesvints, zamon, achmedislamic, massimoselvi liked this article