The Laravel Blade templating engine provides us with a number of conditional directives, namely @if
, @unless
, @isset
, @empty
, and even directives for checking common use cases such as user authentication and environment name.
Some examples:
@if (count($records) === 1)
I have one record!
@elseif (count($records) > 1)
I have multiple records!
@else
I don't have any records!
@endif
@auth
// The user is authenticated...
@endauth
@guest
// The user is not authenticated...
@endguest
See the complete list of Blade directives in the official documentation.
Problem
Useful as they are, we may need custom conditionals not covered by the directives provided out of the box.
Some scenarios where we may end up with long conditionals:
- Although internationalisation and localisation are ideally managed outside view templates, we may need conditionals based on the active language, for instance to add CSS styles.
- Our website/app is published to several markets with slightly different requirements but otherwise share the same codebase. Thus we may deal with environments like
market-a-production
,market-a-staging
,market-b-production
,market-b-staging
.- The env names might even be irregular, for instance
production
,staging
,market-b-production
, andmarket-b-staging
.
- The env names might even be irregular, for instance
- ... and other product-specific cases
When we need to write this kind of conditional multiple times, it makes our template files messy and increases typo risk.
Solution
Enter the Blade::if
method. We can make as many as we want in the boot
method of our AppServiceProvider
.
Example from the official documentation:
// app/Providers/AppServiceProvider.php
use Illuminate\Support\Facades\Blade;
class AppServiceProvider extends ServiceProvider
{
public function boot() {
// Start custom conditional
Blade::if('cloud', function ($provider) {
return config('filesystems.default') === $provider;
});
// end
}
}
- The custom conditional directive is called
cloud
(we can use any name we want). - The function takes the passed value as argument. If the
$provider
value passed in the template equals the value ofconfig('filesystems.default')
, it returnstrue
.
Then we can use it like this.
// resources/views/your_template_file.blade.php
@cloud('digitalocean')
// The application is using the digitalocean cloud provider...
@elsecloud('aws')
// The application is using the aws provider...
@else
// The application is not using the digitalocean or aws environment...
@endcloud
More examples
Say our website is available in multiple languages, both left-to-right (such as English) and right-to-left (such as Arabic and Hebrew). We may need to apply different CSS styles or markup based on the language direction. We can configure a custom conditional to accommodate this.
// app/Providers/AppServiceProvider.php
$RTL_LANG = ['ar', 'he']; // One place to modify if we add more RTL languages
Blade::if('langrtl', function () {
return in_array($app()->getLocale(), $RTL_LANG) ? true : false;
});
// resources/views/your_template_file.blade.php
// BEFORE: Long conditional ๐ซ
@if (app()->getLocale() === 'ar' || app()->getLocale() === 'he')
// RTL language stuff...
@endif
// AFTER: More concise ๐
@langrtl()
// RTL language stuff...
@endlangrtl
As another example, we add a conditional that targets multiple environments. โMarket Aโ website uses the environments production
and staging
, while โMarket Bโ website uses market-b-production
and market-b-staging
.
// app/Providers/AppServiceProvider.php
Blade::if('envmarket', function ($market) {
if ($market === 'a') {
return $this->app->environment() === 'staging' || $this->app->environment() === 'production';
} elseif ($market === 'b') {
return $this->app->environment() === 'market-b-staging' || $this->app->environment() === 'market-b-production';
}
});
// resources/views/your_template_file.blade.php
// BEFORE: Long conditional ๐ซ
@if (in_array(App::environment(), ['staging', 'production']))
// Market A stuff...
@if (in_array(App::environment(), ['market-b-staging', 'market-b-production']))
// Market B stuff...
@endif
// AFTER: More concise ๐
@envmarket('a')
// Market A stuff...
@elseenvmarket('b')
// Market B stuff...
@endenvmarket
Conclusion
Ideally, we should have as little logic as possible in our view templates and delegate it to controllers, services, and helper functions instead. In reality, it's not always 100% possible and we may need to add custom conditionals to our view template files. The Blade::if
method helps us abstract away frequently-used custom conditionals, and thus keeping our template files tidy.
Top comments (0)