How best to pass parameters to every page?

For example, let’s say that you need to put a link in the footer of every page, but it’s different depending on certain criteria that are determined in middleware:

<?php
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;

$app->add(function (Request $request, Response $response, callable $next) : Response
{
    $ua = $request->getHeader('user-agent');
    $isAndroid = (strpos($ua[0], 'Android') !== false);
    $request = $request->withAttribute('isAndroid', $isAndroid);

    return $next($request, $response);
});

This works and if I check the $request object in my actions I can see that the attribute isAndroid is true or false

The problem is that I need to get this into EVERY page, so I don’t want to put it in every single action.

I’m building on top of @akrabat’s Slim Skeleton so figured I’d be able to do something like this:

<?php
use Interop\Container\ContainerInterface;
use Slim\Views\Twig;
use Slim\Views\TwigExtension;

$container = $app->getContainer();

$container['view'] = function (ContainerInterface $c) : Twig
{
    $settings = $c->get('settings')['view'];
    $view     = new Twig($settings['template_path'], $settings['twig']);
    $view->addExtension(new TwigExtension($c->get('router'), $c->get('request')->getUri()));
    $view->addExtension(new Twig_Extension_Debug());
    $view['isAndroid'] = $c->get('request')->getAttribute('isAndroid');

    return $view;
};

Of course that $request object will be a new one though, so it doesn’t include the attributes set in Middleware and I shouldn’t use that anyway…

So, short of having to add it in every action, what’s a good way to get this attribute into every view?

Thanks

You add a twig global environment variable.

//...
$view     = new Twig($settings['template_path'], $settings['twig']);
//...
$view->getEnvironment()->addGlobal("myvariable", 'myvalue');

How does that get it from the Middleware though? I use that attribute in some other places as well and didn’t really want to use Twig as a container to pass values around. I was hoping to use the $request object. My previous solution does the same thing (ie setting $view['myvariable'] = 'myvalue';)

Oh my bad…

you need to pass the twig view into your middleware using some form of dependency injection.

Sorry, you’ve lost me now. I thought the function signature for the middleware was fixed to receive a $request, $response and callable $next before the route executes? How can I get Twig into the middleware?

You could set it into the view from the middleware itself.

$app->add(function (Request $request, Response $response, callable $next) : Response
{
    $ua = $request->getHeader('user-agent');
    $isAndroid = (strpos($ua[0], 'Android') !== false);

    $view = $this->get('view'); // note that $this === ContainerInterface
    $view->getEnvironment()->addGlobal("isAndroid", $isAndroid);

    return $next($request, $response);
});
2 Likes

OK, THIS I like! This works perfectly! Thanks! I’d completely forgotten about being able to retrieve the container from within the middleware. Thank you so much

1 Like