Skip to main content

By Jesse Schutt

Exploring Laravel's Custom Blade Directives

Earlier today, I was working on coding up a design that displays a varying number of cards - each with a unique title and description… think Masonry/Pinterest-esque.

I’ve been using Model Factories to stub out a bunch of cards, all with different content. Once I’d hooked up the dummy data to the card templates, I realized that the design didn’t work as well with titles that had more than 20 or so characters.

A common solution to this would be to use CSS to break the line and automatically add an ellipsis like this:

.ellipsis { 
    overflow: hidden; 
    white-space: nowrap; 
    text-overflow: ellipsis; 
}

However, this wouldn’t work well in my situation because the design allows titles to be two lines long.

Another solution would be to chop off the title at a given length and add an ellipsis using a php snippet like this:

$truncatedTitle = substr($title,0,20) . '...';

But, what if the title is less than 20 characters to start with? We wouldn’t want the snippet to add the ellipsis in that case.

$truncatedTitle = strlen($title) > 20 ? substr($title,0,20)."..." : $title;

By combining a string length check with a ternary operator, we can truncate and add the ellipsis if necessary. If the title is less than 20 characters, we just return it as normal.

None of this is very complicated if you are familiar with vanilla PHP.

However, adding this much PHP to my Blade templates would have really mucked up my otherwise-clean templates. So I decided to drop this functionality into a custom Blade directive that I could reuse where necessary.

Defining a custom Blade directive

Fortunately for us, defining a custom Blade directive is a pretty straightforward process. Open up your AppServiceProvider.php file and look for the boot() method.

The basic format goes as follows:

<?php

namespace App\Providers;

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

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Blade::directive('helloWorld', function(){

            return "<?php echo 'Hello World'; ?>";
        });
    }
}

The first parameter will be the name of your directive, which can then be used in your templates.

According to the code above, adding @helloWorld to your template will result in ‘Hello World’ printed to the screen.

<?php

namespace App\Providers;

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

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Blade::directive('hello', function($expression){

            return "<?php echo 'Hello ‘ . {$expression}; ?>";
        });
    }
}

By using a closure we can pass data into the directive. Therefore, @hello(‘Jesse’) will result in ‘Hello Jesse’ being displayed in the template.

The custom @truncate directive

<?php

namespace App\Providers;

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

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Blade::directive('truncate', function($expression){

            list($string, $length) = explode(',',str_replace(['(',')',' '], '', $expression));

            return "<?php echo e(strlen({$string}) > {$length} ? substr({$string},0,{$length}).'...' : {$string}); ?>";
        });
    }
}

Breaking it down

The data passed through to the closure comes in as a string. So if you send @truncate($list->title, 20), the value of $expression will be ($list->title, 20). Unfortunately we cannot pass arrays or objects, so we need to remove the parenthesis and explode the string into variables on the comma. Once we have the variables, we can check the length, truncate, and add an ellipsis if necessary.

Side note: the e() function is a Laravel helper method that runs htmlentities() over a string. In our case, we don’t want the @truncate method to actually display HTML code, so we are using e().

Now I can use @truncate($card->title, 20) and get a properly formatted title, either with or without an ellipsis, depending on the length. Cool!

Want to read more tips and insights on working with a Laravel development team that wants to help your organization grow for good? Sign up for our bimonthly newsletter.

By Jesse Schutt

Director of Engineering

Jesse is our resident woodworker. His signature is to find the deeper meaning in a project and the right tool for the job.