简体   繁体   中英

Setting global session var in Slim4 and Twig

I'm been having issues with this for weeks on numerous plugins/extensions, so I am afraid I'm stuck.

It would be very helpful if I can use session data in all Twig templates, not just the ones parsed by Controllers via the Render method, like this which is working fine:

$current_session = $this->container->get('session');

return $this->container->get('twig')->render(
  $response,
  '/user/login.html.twig',
  [
    'title'        => "Please login",
    'session_user' => $current_session->user,
    "session_id"   => $current_session::id()
  ]
);

So here's what I have been trying for|with Slim/Session (by bryanjhv/slim-session) to get data straight into TWIG views. I've had similar issues with Slim/CSRF so I quit trying to add that due to mental sanity issues for trying too long;-)

So, here's what I have in my Container file:

...

'twig' => function (Container $container) {
    $twig = Twig::create(VIEW_PATH, [
        'cache' => false,
        'auto_reload' => true
    ]);
    $twig->addExtension(new IntlExtension());

    $environment = $twig->getEnvironment();
    $environment->addGlobal('user', (object)['name' => 'xXx']);
    
    return $twig;
},

// 'sessions'
'session' => function () {
    return new Helper();
},

...

Session is started in middleware.php which is included via index.php

...
// Session
$app->add(new Session([
    'autorefresh' => true,
    // 'domain'      => 'localhost',
    // 'handler'     => null,
    'httponly'    => false,
    'lifetime'    => '1 hour',
    'name'        => 'f_session',
    'path'        => '/',
    'samesite'    => 'Lax',
    'secure'      => false,
])); 
...

Index.php

...
$app->add(new TwigSessionVarsMiddleware($container));
...

My entire TwigSessionVarsMiddleware.php

declare(strict_types=1);

namespace App\Middlewares;

use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Slim\Psr7\Response;
use DI\Container;

class TwigSessionVarsMiddleware
{
    protected $container;

    public function __construct(Container $container)
    {
        $this->container = $container;
    }

    /**
     * Example middleware invokable class
     *
     * @param  ServerRequest  $request PSR-7 request
     * @param  RequestHandler $handler PSR-15 request handler
     *
     * @return Response
     */

    public function __invoke(Request $request, RequestHandler $handler): Response
    {
        $response = $handler->handle($request);
        $existingContent = (string) $response->getBody();

        $response = new Response();

        // Get and Set Twig Globals
        $this->container->get('twig')->getEnvironment()->getGlobals()['user'];
        $current_user = $this->container->get('session');

        $this->container->get('twig')->getEnvironment()->addGlobal("user", [
            'id' => $current_user::id(),
            'name' => $current_user->user,
        ]);

        $userdata = $this->container->get('twig')->getEnvironment()->getGlobals()['user'];
        $response->getBody()->write($userdata['id'] . $existingContent);

        return $response;
    }
}

The last 2 lines in the middleware are there for testing purposes, it will display the correct values on top of the template file as expected.

Also, the following is echo'ed just fine as well in the templates, however this is only the initial value set in the container, never the updated value in the middleware.

        {{ user.name }}

I can not get any session data in my main index.php either, I've been struggling with the CSRF extension too and I'm afraid I am missing some key points. I must have been close at least a couple times after a gazillion tries.

Any input from anybody else? My Google search returned 8 (.) results that did not help.

*** UPDATE ***

Appently I'm really bad in figuring out how middleware works correctly. I moved the session part in middleware.php to the index and now sessions are available in Twig by default. Next I'll see if I can actually use CSRF as well.

...
AppFactory::setContainer($container);

/******************************************************
 * Create App
 *****************************************************/
$app = AppFactory::create();

/******************************************************
 * Load Sessions
 *****************************************************/
$app->add(
    new Session([
        'name' => 'f_session',
        'autorefresh' => true,
        'lifetime' => '1 hour',
    ])
);
...

Okay, turned out I only needed to change Slim\Psr7\Response; to Psr\Http\Message\ResponseInterface as Response;

CSRF integration still doesn't work though, but that's another challenge.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM