Skip to content

An Introduction to Composers in Sage 10

If you’re new to working with Sage 10, one of the most important to concepts to learn about is the use of composers.  In Sage 10, composers allow you to fetch data while keeping your back end logic separate from your front end code.  Note that Sage 10 composers are completely different from the composer package manager in PHP.

For instance, in a traditional non-Sage WordPress theme, if you want to get data for a template, you can either get the data directly inside of your template’s PHP file, which mixes HTML with PHP code, or you can create a function and place it in your functions.php and call your function directly from your template file.

While these approaches work, they’re messy.  Putting query logic directly inside of your template makes it hard to read your code and even harder to re-use your back end logic code, such as a query.  Putting your back end logic in functions.php is a little better, but you can soon end up with a long file that’s a mix of different unrelated methods.

With Sage 10 and composers, these problems are solved.  You typically have one composer for each unique section of your site and then you pass data from this composer to the blade views that require that data.

Looking at a Basic Composer

Let’s start off by looking at a basic composer.  The composers are located under the App > View > Composers folder of your Sage 10 theme.  Composers are autoloaded, so if you create a new one it will be detected automatically.

Out of the box, Sage 10 comes with a few basic composers, the most basic of those is the App.php composer.  Let’s take a look at this composer:

<?php

namespace App\View\Composers;

use Roots\Acorn\View\Composer;

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

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

    /**
     * Returns the site name.
     *
     * @return string
     */
    public function siteName()
    {
        return get_bloginfo('name', 'display');
    }
}

At less than 40 lines long, the composer is small but packs a mighty punch.  Let’s break it down:

Namespace and Class Declaration:

At the very top, you have your namespace and class declarations, pretty standard stuff in the PHP OOP world.  Then you have your class declaration:

class App extends Composer

The name of your class should match the name of your file, same as with any other PHP class.  Your composer’s class should extend the Roots\Acorn\View\Composer class, which you can see is defined above the class declaration.

Define Views Served By Your Composer:

The next piece of the composer is where you determine what views will receive data from this composer.  This is controlled by the $views variable, which contains an array of data.  You can be as broad or as specific as you wish here.  Keep in mind though that any time a view that is loaded that you specify here, the composer will fetch that data.  If you are doing something that can slow your site down, such as a database query, you will improve performance by ensuring you only load the composer on the views that absolutely need that data.

At the most broad level, you can simply pass in a value of * (asterisk) which means that the data for the composer will be passed to EVERY blade view on your site.  This might be useful for some things, like getting the site name, but will slow your site down if you’re passing something performance heavy to every single view.

You can also pass data to one or more views by changing the contents of the $views array.  The paths for your views should start from the root of your resources > views directory of your theme.  You can add data from a composer to more than one view like this:

protected static $views = [
    'partials.page-header',
    'partials.content',
    'partials.content-*',
];

In the above example, we’re passing the data from the composer to several views.  You may also notice that you can do a partial wildcard when defining your views, such as partials.content-* in the above example.  This can be really useful when you want to pass the same data to several views at once or several views with a similar name or similar purpose.

Loading the Correct Data For Your Views:

To actually pass data to your views, you need to define that data using the with() method, which should return a key / value array.  In this array, the keys are the names of the variables that you wish to use inside of your blade views, so for instance an array key of mobile_logo in your method would allow you to access that value in your blade view using a variable named $mobile_logo.

As far as the values, here’s where things get interesting.  You can put a literal string or number in here or a call to another function where you’ll get more data.  If you’re getting your data from another function, it can either be a function external to your current class or it can be internal to your current class, which you reference by using $this.

For instance, going back to our App.php file from earlier, you’ll see that if we strip out all of the comments, we get the following:

public function with()
{
    return [
        'siteName' => $this->siteName(),
    ];
}

public function siteName()
{
    return get_bloginfo('name', 'display');
}

From within our with() method we call the siteName() function that lives in the same App.php file.  This results in the name of the blog being returned to your blade view, which you can reference with a variable named $siteName.

Note that WordPress functions are executed in a context inside of the loop, so that you can use default WordPress functions here as well as even run functions specific to the current post, such as get_the_ID().

Simplifying Things Even Further:

Even though in the above example, we’re calling a separate method called siteName() to get the data, in this context it’s completely unnecessary.  In fact, you can simplify things by omitting the siteName() method entirely and just directly passing the requested data within the with() method:

public function with()
{
    return [
        'siteName' => get_bloginfo('name', 'display'),
    ];
}

For one liners like this, it makes it super easy to pass data directly to your view while keeping your composer class file clean.  For more complicated code, such as fetching results from a database, you should use a method local to your composer, as shown using the siteName() method.

Using your data in your Blade views:

As previously stated, if you want to use data that is fetched using a composer in a blade view, you simply reference it using a variable.  At the most simplest step, you can echo out the contents of your variable like this:

<img src="{{ $desktop_logo_default['url'] }}" alt="{{ $siteName }}" width="{{ $desktop_logo_default['width'] }}" height="{{ $desktop_logo_default['height'] }}" class="logo-img logo-img-desktop logo-img-desktop-nonsticky" />

Using the blade {{ }} syntax allows you to output a variable’s contents while stripping out any HTML.  In the event that you need to allow HTML content, such as when getting data from a WYSIWYG editor, you can use the {!! !!} syntax instead.  For more information on outputting data in your blade templates, see the Blade Templates documentation.

Note that you can have multiple composers pass data to the same blade view.  In the example above, I’m getting the $siteName variable from the App.php composer while the other data for the image is being passed from a completely separate composer.

In Conclusion:

Wrapping up, Sage 10 composers are a powerful feature that help keep your front end Blade files looking clean while also offering an easy way to send the same data to multiple blade views at once.

If you liked this article, you might also like my Sage 10 Installation Tutorial or my Sage 10 Multisite Tutorial.  If you found this content helpful, please share it.  If you want to learn more about Sage 10 or would be interested in working with me directly, check out my developer mentorship service, where I’ll show you how to use Sage 10 as well as other advanced WordPress development techniques.  The initial consultation is free and there’s no obligation.

Leave a Reply

Your email address will not be published. Required fields are marked *