Getting information into master template

Trying to figure out the best way to get some variables into the master twig template. Will be needed to do individually for every route, or sometimes for a group to simplify things.

This is the group and route I have right now, and it seems to work. The globalTemplateVars middleware gets all the data for the header and footer of site , and the other closure middleware allows to get some variables into the header and footer template.

$app->group('/getpassword', function (RouteCollectorProxy $group) {

    $group->map(['GET', 'POST'],'/', \App\Application\Controllers\PasswordResetController::class .':index');
// some more routes related to password reset here.

    ->add(function (Request $request, RequestHandler $handler) use ($app) {
    $setupVars = array(
        'forgotpasswordpage' => true,
        'SECTION' => 'ADMIN'

    $this->set('setupVars', $setupVars);
    $response = $handler->handle($request);
    return $response;

This is the middleware that populates the master twig template for the header and footer

$globalTemplateVars = function (Request $request, RequestHandler $handler) use ($app) {
         * @var \Slim\Views\Twig
        $view = $this->get('view');
        $templatesData = $this->get('MasterTemplateDataLoader')->getData();
        $view->getEnvironment()->addGlobal('global', $templatesData);
        $this->set(Twig::class, $view);
        $response = $handler->handle($request);
        return $response;

Here are my issues that need to figure out…

  1. is there a better way to inject some route conditional variables into the globalTemplateVars middleware before it runs? When I had globalTemplateVars on the group but defined the vars on or in the route, it wasn’t early enough to get the vars in there.

  2. is there a way to not populate the master twig view template until it’s used similar to ViewComposers in Laravel?

  3. I am hoping to not have to call the globalTemplateVars middleware or the closure middleware on every route. Something more programatic would be nice.

This all based on how our legacy pages are constructed which we’re migrating away from.

$someVar = true;

require_once header (use $someVar in here to do something like load DataTables library, or to not enforce login on a page, etc)

some code in the page

require_once footer

With PHP-DI and constructor (dependency) injection you could let the container inject the object with data into the controller/action classes you need.

I’m with odan.
You could make it a dependency of the request handler constructor. Inject only in the Handler classes you need. Any container implementation could help you with that.
But your use of middlewares for doing that is also good I think. The only difference is with a container with autowiring you only have to make that definition once and then add it as a dependency where you need to. :slight_smile:

Thanks for the replies. Based on thought from @odan it gave me the idea to inject the class that loads all the master template stuff and have it return an instance of twig view so that can act on it in a chain in the controller function, essentially mimicking a require_once in a way…but still being able to dictate it for each route

return $this->headerAndFooter->getData(array(
            'forgotpasswordpage' => true,
            'SECTION' => 'ADMIN'
        ))->render($response, 'passwordreset/index.twig', $templateData);
1 Like