Roots Sage 10 using view Composers outside of app directory

2.4k Views Asked by At

For anyone who is familiar with Sage 10, I am trying to get View Composers working outside of the default app/View/Composers directory. I have another directory Composers inside the parent directory of the Sage 10 directory and loaded it in correctly through PSR-4. This is working fine.

However, it does not seem to work. I wonder if I have to register my 'custom' Composer directory somewhere, but the documentation on Sage 10 is very shallow to non-existent.

So in the parent of my Sage dir, there is a Composers dir that gets loaded though PSR-4 containing an Application.php which looks like this:

<?php

namespace Composers;

use \Roots\Acorn\View\Composer;

class Application extends Composer
{

    /**
     * List of views served by this composer.
     *
     * @var array
     */
    protected static $views = [
        'partials.header',
    ];

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

    public function sayHello()
    {
        return 'Hello from Composer';
    }
}

I have tried adding the view composer in the view config of Sage 10 by adding (without any luck)

'composers' => [
    Composers\Application::class,
],

Does anyone know where to 'register' these custom Composers? I have to note that PSR-4 is autoloading the classes correctly.

Edit The Sage 10 repository can be found here: https://github.com/roots/sage

2

There are 2 best solutions below

0
On

I was searching for this answer and figured it out. In my use case, I needed to extract data from my root App composer through a method I created. Similar to your sayHello() public function. I needed it in a PHP file outside of Sage 10's root app directory. It was to overwrite a plugin's (The Events Calendar) template file.

I realized, that this App composer was just a class object... and sage does a TON of use statement imports. So at the top of my PHP file I added:

use App\view\Composer\App

This loaded the class into my PHP file with no issues. Next, I attempted to use it in the following way:

$sageAppComposer = new App();
$globalSocialMediaNetworkLinks = $sageAppComposer->globalSocialNetworkLinks();

This worked! The data returned from my function was saved to $globalSocialMediaNetworkLinks. As a result, given your example... you could do the following:

use App\view\Composer\Application
$sageApplicationComposer = new Application();
echo $sageApplicationComposer->sayHello();

Hope this helps!

0
On

A response for future devs: find their discourse it's slightly better.

These are being loaded in the Roots\Acorn\View\ViewServiceProvider class. The method checks to make sure that config array you set is associative before loading, with Arr::isAssoc.

So this checks to make sure the array has keys, but it does not use them. Maybe they're relevant elsewhere... ::shrug::

/**
 * Attach View Composers
 *
 * @return void
 */
public function attachComposers()
{
    $composers = $this->app->config['view.composers'];

    if (is_array($composers) && Arr::isAssoc($composers)) {
        foreach ($composers as $composer) {
            $this->view()->composer($composer::views(), $composer);
        }
    }
    ...
}