← All posts

Passing Custom Data to Blade Templates with Sage View Composers

Passing Custom Data to Blade Templates with Sage View Composers

When I first started diving deep into WordPress theme development, I was instantly frustrated by the common practice of cramming all sorts of data fetching logic directly into template files. You’d open up `archive.php` or `single.php` and be greeted by `WP_Query` instances, conditional checks, and database calls all mixed in with the HTML markup. It was a chaotic mess, a recipe for unmaintainable code, and miles away from any clean architecture principles I’d learned in other development contexts. Then I found Sage, and specifically, its approach to data handling with View Composers, and it completely changed my perspective on WordPress.

Sage, built on top of Laravel's components via Acorn, offers an MVC-like structure that makes WordPress development feel truly modern and enjoyable. It empowers us, as developers, to write organized, programmatic code, which is a stark contrast to the database bloat and UI-driven complexity of tools like Divi or Elementor. The beauty of Sage lies in its commitment to separating concerns: your Blade templates are purely for presentation, and your data logic lives where it belongs.

Today, I want to walk you through a specific, concrete technique that embodies this philosophy: using a View Composer to fetch custom data and pass it cleanly to your Blade templates. This keeps your templates lean and focused solely on displaying information, while all the heavy lifting of data retrieval happens behind the scenes.

Let's say you have a custom post type called "Projects" and you want to display the three most recent projects in a sidebar partial (`resources/views/partials/recent-projects.blade.php`). Traditionally, you might throw a `new WP_Query` directly into that partial. With Sage, we leverage a View Composer.

First, we create our View Composer. I usually place these in `app/View/Composers`. So, let’s create `app/View/Composers/RecentProjects.php`:

namespace App\View\Composers;

use Roots\Acorn\View\Composer;

class RecentProjects extends Composer { /** * List of views served by this composer. * * @var array */ protected static $views = [ 'partials.recent-projects', ];

/** * Data to be passed to view before rendering. * * @return array */ public function with() { return [ 'projects' => $this->getRecentProjects(), ]; }

/** * Get the three most recent projects. * * @return \WP_Post[] */ protected function getRecentProjects() { $query = new \WP_Query([ 'post_type' => 'project', 'posts_per_page' => 3, 'post_status' => 'publish', 'orderby' => 'date', 'order' => 'DESC', 'no_found_rows' => true, // Optimize for performance if pagination isn't needed ]);

return $query->posts; } }

In this composer, `static $views` tells Sage which Blade templates this composer should apply to. The `with()` method returns an associative array, where the keys become variables available in your Blade template. Here, we're calling a protected helper method `getRecentProjects()` to encapsulate the `WP_Query` logic.

Next, we need to register this composer so Sage knows about it. The easiest place for theme-specific composers is usually `app/setup.php`. Just add it to the `compose` array:

add_filter('sage.view.composers', function ($composers) { return array_merge($composers, [ \App\View\Composers\RecentProjects::class, ]); });

Now, within your `resources/views/partials/recent-projects.blade.php` file, you can access the `projects` variable directly, without any `WP_Query` calls cluttering your markup:

<section class="recent-projects"> <h2>Our Latest Projects</h2> @if (!empty($projects)) <ul> @foreach ($projects as $project) <li> <a href="{{ get_permalink($project->ID) }}"> <h3>{{ get_the_title($project->ID) }}</h3> </a> </li> @endforeach </ul> @else <p>No recent projects to display.</p> @endif </section>

See how clean that template is? It’s purely presentation. All the logic for *what* projects to fetch, *how many*, and *how* to query the database is handled entirely within the `RecentProjects` View Composer. This pattern provides immense benefits: your templates are easier to read and maintain, your data fetching logic is reusable and testable, and you maintain a clear separation of concerns. This is why Sage stands out as the developer's choice for building robust, clean, and maintainable WordPress themes. It encourages a structured, programmatic approach that modern web development demands, leaving the old, spaghetti-code ways behind.