Skip to main content
Sage View Composers: Keeping Your Blade Templates Presentation-Pure

Sage View Composers: Keeping Your Blade Templates Presentation-Pure

You’ve likely felt the frustration of building WordPress themes that quickly devolve into an unmaintainable tangle.

You’ve likely felt the frustration of building WordPress themes that quickly devolve into an unmaintainable tangle. The traditional WordPress loop, sprinkled with get_posts calls or even custom queries directly within your index.php or page.php files, quickly makes templates difficult to read, reuse, and debug. This is precisely the kind of programmatic chaos that Sage, built on top of Laravel’s excellent componentry like Blade and Acorn, seeks to eliminate. We developers choose Sage because it brings an MVC-like structure to WordPress, letting us create clean, presentation-focused templates completely divorced from data retrieval logic.

Today, I want to dive into a specific technique that embodies this philosophy: View Composers. If you’ve ever found yourself asking, “How do I get complex data into my Blade templates without cluttering them up?”, then View Composers are your answer. They provide a powerful, centralized way to bind data to views, ensuring your Blade files remain purely responsible for displaying information, not fetching it. This is a stark contrast to the database bloat and code spaghetti often found in themes built with drag-and-drop page builders like Divi or Elementor, which, while offering quick visual builds, often sacrifice long-term maintainability and developer sanity.

Let’s consider a common scenario: you have a custom post type, say “Projects,” and you want to display a list of these projects on your home page, perhaps filtered by a custom taxonomy or other criteria. The “old” way, even with Blade, might involve something like this directly in resources/views/partials/projects-list.blade.php:

@php
    $args = ['post_type' => 'project', 'posts_per_page' => 3];
    $projects = get_posts($args);
@endphp

@if (!empty($projects))
    <section class="projects">
        <h2>Latest Projects</h2>
        @foreach ($projects as $project)
            <article>
                <h3>{{ $project->post_title }}</h3>
                <p>{{ $project->post_excerpt }}</p>
                <a href="{{ get_permalink($project->ID) }}">View Project</a>
            </article>
        @endforeach
    </section>
@endif

While this works, it pollutes your Blade template with data fetching logic. The template is no longer just about presentation; it’s also about how to get the project data. This makes the projects-list.blade.php less reusable and harder to test.

This is where View Composers shine. We can extract that data fetching logic into a dedicated class and compose it into our view when needed. First, let’s create a new class, say app/View/Composers/ProjectsComposer.php:

namespace App\View\Composers;

use Roots\Acorn\View\Composer;

class ProjectsComposer extends Composer
{
    /**
     * List of views served by this composer.
     * @var array
     */
    protected static $views = [
        'partials.projects-list',
        'front-page', // Or any other view that needs this data
    ];

/**
     * Data to be passed to view before rendering.
     * @param  array  $data
     * @return array
     */
    public function with()
    {
        $args = [
            'post_type'      => 'project',
            'posts_per_page' => 3,
            'orderby'        => 'date',
            'order'          => 'DESC',
        ];

return [
            'projects' => get_posts($args),
        ];
    }
}

Now, instead of manually instantiating this composer, we register it with Acorn. The simplest way is to add it to your config/view.php file under the composers array, or for a more structured approach, within a service provider. Let’s stick to the setup.php for quick setup for this example, although a dedicated service provider offers more robust organization for complex applications. In app/setup.php, within the add_filters() function or directly after it:

add_action('after_setup_theme', function () {
    // Other theme setup...
    Roots\view()->composer(['partials.projects-list', 'front-page'], \App\View\Composers\ProjectsComposer::class);
});

With this in place, your resources/views/partials/projects-list.blade.php becomes wonderfully simple and purely presentational:

@if (!empty($projects))
    <section class="projects">
        <h2>Latest Projects</h2>
        @foreach ($projects as $project)
            <article>
                <h3>{{ $project->post_title }}</h3>
                <p>{{ $project->post_excerpt }}</p>
                <a href="{{ get_permalink($project->ID) }}">View Project</a>
            </article>
        @endforeach
    </section>
@endif

Notice how the $projects variable is simply available in the template. The template doesn’t care how $projects got there; it just knows it needs to display them. This drastically improves readability, makes testing the data fetching logic (ProjectsComposer) separate from the presentation, and enhances the reusability of your Blade templates.

This technique is a cornerstone of building robust, maintainable Sage themes. By consistently separating data retrieval from presentation using View Composers and Blade, you’re not just writing code; you’re crafting an organized, programmatic codebase that scales, adapts, and remains a joy to work with, rather than a constant source of frustration and refactoring. Embrace the Sage way, and free your templates from data-fetching burdens!