Sculpting Clean Data for Your Sage Templates with View Composers
If you’ve spent any time battling WordPress themes, you know the struggle: templates crammed with database queries, conditional logic tangled with HTML, and a general sense of "where does this data even come from?" The traditional WordPress development model, while flexible, often encourages a monolithic approach where presentation and business logic become inextricably intertwined. This isn't just an aesthetic problem; it’s a maintenance nightmare that grows exponentially with project complexity, leaving a codebase that's fragile and difficult to extend. It’s a stark contrast to the bloated database tables and inaccessible code that page builders like Divi or Elementor generate, but still far from ideal for serious developers.
This is precisely where Sage, with its MVC-like architecture, shines as the modern developer’s choice. One of its most powerful features for bringing order to data chaos is the View Composer. Forget sprinkling `WP_Query` objects and `get_post_meta()` calls directly into your Blade files. With Sage, your templates become truly presentation-focused, receiving exactly the data they need, already prepared and structured. View Composers act as the bridge, allowing you to prepare data for your views cleanly and programmatically, maintaining that crucial separation of concerns.
Let’s walk through a concrete example. Imagine you’re building a portfolio site and need to display custom post type entries for "Projects." Each project has a title, content, and a custom field for a "Client Name." Instead of fetching all this within your `single-project.blade.php` or a partial, we’ll use a View Composer to deliver a neat `project` object to our template.
First, we define our composer. Inside your `app/View/Composers` directory, create a file named `ProjectComposer.php`:
namespace App\View\Composers;
use Roots\Acorn\View\Composer;
class ProjectComposer extends Composer { /** * List of views served by this composer. * * @var array */ protected static $views = [ 'single-project', 'partials.content-project', ];
/** * Data to be passed to view before rendering. * * @param array $data * @return array */ public function with($data) { global $post; // Get the global post object for the current CPT
// Basic post data $project_data = [ 'id' => $post->ID, 'title' => get_the_title($post), 'content' => apply_filters('the_content', $post->post_content), ];
// Custom field data $project_data['client_name'] = get_field('client_name', $post->ID); // Using ACF, for example
return array_merge($data, [ 'project' => (object) $project_data, // Pass as an object for clean access ]); } }
In this composer, `protected static $views` tells Sage which templates this composer should apply to. The `with()` method is where the magic happens. We retrieve the global `$post` object, extract the necessary data, including a custom field `client_name` (assuming ACF for simplicity), and then pass it to the view under a clean `project` variable. Notice we’re casting it to an object for cleaner access in Blade.
Next, we need to register this composer. Open your `config/view.php` file (or create one if it doesn't exist) and add it to the `composers` array:
'composers' => [ 'single-project' => \App\View\Composers\ProjectComposer::class, 'partials.content-project' => \App\View\Composers\ProjectComposer::class, ],
Now, in your `resources/views/single-project.blade.php` or `resources/views/partials/content-project.blade.php`, you can access your data like this:
<article @php(post_class())> <header> <h1>{{ $project->title }}</h1> @if ($project->client_name) <p>Client: {{ $project->client_name }}</p> @endif </header> <div class="entry-content"> {!! $project->content !!} </div> </article>
See how clean that template is? No PHP, no database calls, no complex logic. It simply receives a `project` object and displays its properties. This separation makes your templates incredibly readable and your data logic centralized and testable. If you need to change how `client_name` is fetched or add new project details, you only touch the `ProjectComposer`, not half a dozen templates. This dramatically improves maintainability and ensures a consistent approach to data handling across your entire theme.
This pragmatic application of View Composers is just one facet of why Sage, powered by Acorn's dependency injection capabilities, empowers developers to build truly robust, maintainable, and modern WordPress themes. It frees you from the tangled mess of traditional WordPress development, offering an organized, programmatic codebase that stands in stark contrast to the unmaintainable database bloat and inline styling of page builders. Embrace Sage, embrace sanity.