Accessing the Cascade in Blade with Statamic’s @cascade Directive

Published in Laravel on Aug 30, 2024

Statamic 5.23.0 caught my eye with an awesome PR from Jack Sleight which lets you use cascade data in Blade with a new @cascade directive. It is now documented here in the statamic docs too.

At my job, we've integrated Statamic CMS into an existing Blade/Livewire app of ours. One small pain point has been running into situations where the Cascade (Statamic's data inheritance model) wasn't easily available in Blade. This meant that I had to do extra work to access supposedly "global" variables set in the control panel.

What is the Cascade in Statamic?

Statamic's docs do a good job of explaining this, but it's still worth touching on because it's totally different way of thinking about data than what most Laravel/Blade developers will be used to.

In Statamic, the cascade lets you define variables at different levels of specificity. Then, when you use a variable in your views, it cascades down an order of fallback locations looking for that variable.

In Antlers, Statamic's default templating engine, the cascade just works. However, as Jack noted in the PR, the cascade isn't always directly available in all blade templates, leading a to a need for the @cascade directive he contributed.

Example: a Simple Component for OpenGraph Tags

In our Laravel application, we wanted to be able to set a global fallback OpenGraph image in the Statamic Control panel that would apply to all pages without a specific image. The @cascade directive works just like @props, so after creating an opengraph global, I could use the directive to pass the new global into a blade component:

@cascade([
    'opengraph'
])
@props([
    'title',
    'description' => null,
    'url'
])
@isset($opengraph->fallback_og_image)
<meta name="og:title" content="{{ $title }}">
<meta name="og:type" content="website">
@isset($description)
    <meta name="og:description" content="{{ $description }}">
@endisset
<meta name="og:image" content="{{ $opengraph->fallback_og_image->permalink }}">
<meta name="og:url" content="{{ $url }}">
<meta name="og:site_name" content="{{ config('app.name') }}">
@endisset

This probably doesn't look like anything too crazy... but that's kind of the point. This solution feels like a natural marriage of Blade and Statamic. And it's clear exactly what data from the cascade I am using in the component. Before 5.23.0, I found myself having do stuff like using query builders to pick out individual globals in the views that needed them (yuck). Now, I think we have a nice idiom to use instead baked right into Statamic core. Thanks, Jack!

Beyond the obvious maintainability benefits, I think using @cascade should help performance because there is a cost to the extra queries you have to make when you can't access the cascade. (You can see this with the debugbar in Statamic 5). In our site, this led to a 5% performance gain in load testing, but your milage may vary, obviously.

Likely due to it working like @props, Github Copilot seemed to pick up on how to use it pretty well already in my project, which is not a given when working with new blade directives in my experience.

Blade vs. Antlers Templates: Why not Both?

Another Blade directive I've been using a lot is @antlers to use antlers right in my templates. Your IDE might complain, but I think it's a good way to get the best of both worlds when working with Statamic in a Blade-based project. And @cascade helps this because you should now run into fewer situations where "Antlers inside Blade" behaves differently than you expect.

I think it's great to see Blade continue to get better integration in Statamic. Although Antlers is still the number 1 option when it comes to templating for sites built in Statamic, Blade seems to be nearing something a little closer to parity these days (at least to my eyes).

Is @cascade something you'll use in developing Statamic sites? Tell me about it in the comments! I've only used it for globals so far, but I think the new possibilities go way beyond that.

Comments

Join the conversation and feel free to ask any questions you may have! Please note that submitted comments may be subject to approval before appearing on the site.