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.
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?
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:
namespace App\Providers; use Illuminate\Support\ServiceProvider; use Illuminate\Support\Facades\Blade; 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'; }); } }
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.
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
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:
namespace App\Providers; use Illuminate\Support\ServiceProvider; use Illuminate\Support\Facades\Blade; 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:
namespace App\Providers; use Illuminate\Support\ServiceProvider; use Illuminate\Support\Facades\Blade; 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.
namespace App\Providers; use Illuminate\Support\ServiceProvider; use Illuminate\Support\Facades\Blade; 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('Taylor') </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:
namespace App\Providers; use Illuminate\Support\ServiceProvider; use Illuminate\Support\Facades\Blade; 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:
namespace App\Providers; 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.