A custom Blade directive extends the template syntax itself — genuinely useful for a repeated pattern (formatting a price, checking a custom permission) that would otherwise need the same verbose PHP or conditional repeated across many views.
Registering a simple directive
// AppServiceProvider boot() method
use Illuminate\Support\Facades\Blade;
public function boot(): void
{
Blade::directive('currency', function ($expression) {
return "";
});
}
@currency($product->price)
The directive's callback receives the expression inside the parentheses as a raw string and must return a string of valid PHP code — Blade inserts this returned PHP directly into the compiled template, which is why the callback effectively writes PHP code as text, rather than executing anything itself.
A directive with a conditional (if/endif pair)
Blade::if('role', function (string $role) {
return auth()->check() && auth()->user()->hasRole($role);
});
@role('admin')
Admin Panel
@endrole
Blade::if() is a higher-level helper specifically for creating conditional directives — it automatically generates the matching @role/@endrole (and @elserole) pair from a single boolean-returning callback, without needing to manually write the raw PHP if/endif code that Blade::directive() would require for the same result.
A directive that accepts multiple arguments
Blade::directive('datetime', function ($expression) {
return "format('M d, Y \a\\t g:i A'); ?>";
});
@datetime($order->created_at)
A block-style directive, with a matching end tag
Blade::directive('cache', function ($expression) {
return "";
});
Blade::directive('endcache', function ($expression) {
return "";
});
A directive pair like this uses PHP's own output buffering (ob_start()/ob_get_clean()) to capture everything rendered between the two directives — genuinely more advanced than a single-expression directive, and worth reaching for only when the directive needs to wrap a block of template content, not just transform one value.
Where to register custom directives in a real project
Registering directives inside AppServiceProvider::boot() (as shown) works fine for a small number of them — for a project accumulating many custom directives, extracting them into a dedicated service provider (like a BladeServiceProvider) keeps AppServiceProvider from growing cluttered with unrelated registration logic.
Why a directive isn't always the right tool
A directive is genuinely worth creating for something used across many different views — for logic specific to just one or two templates, a plain @if with a model method or accessor (like $product->isOnSale()) is simpler and doesn't require registering anything globally just to be understood by another developer reading the template.