Using zend-expressive-session-cache as PSR-6 session persistence adapter in Expressive 3
zend-expressive-session-cache is a PSR-6 session persistence adapter for zend-expressive-session that can be used in Expressive 3. In current post, I will provide the use case of it with apcu for cache adapter with zend-cache for cache item pool.
Let’s start with create new project from skeleton with the following command:
➜ composer create-project \ zendframework/zend-expressive-skeleton \ expressive3-cache-tutorial
After the skeleton installed, we can require the zendframework/zend-expressive-session-cache
and zend-cache
with the following command:
➜ cd expressive3-cache-tutorial ➜ composer require \ zendframework/zend-expressive-session-cache \ zendframework/zend-cache
Now, ensure config/config.php
has the following ConfigProvider
s registered:
<?php // config/config.php $aggregator = new ConfigAggregator([ // ... \Zend\Cache\ConfigProvider::class, \Zend\Expressive\Session\Cache\ConfigProvider::class, \Zend\Expressive\Session\ConfigProvider::class, // ... ], $cacheConfig['config_cache_path']);
For apcu
adapter, we need the apcu
extension to be installed, we can install via pecl
like the following:
➜ sudo pecl install apcu
After it installed, we need to set apc.use_request_time = 0
in php.ini like the following:
# your php.ini apc.use_request_time = 0
For Cache Item Pool service, we can create a factory for it, for example, like the following:
<?php // src/App/Cache/CacheItemPoolFactory.php declare(strict_types=1); namespace App\Cache; use Psr\Cache\CacheItemPoolInterface; use Psr\Container\ContainerInterface; use Zend\Cache\Psr\CacheItemPool\CacheItemPoolDecorator; use Zend\Cache\StorageFactory; final class CacheItemPoolFactory { public function __invoke(ContainerInterface $container) : CacheItemPoolInterface { $storage = StorageFactory::factory([ 'adapter' => [ 'name' => 'apcu', ], ]); return new CacheItemPoolDecorator($storage); } }
We can register then the cache pool service and make alias of SessionPersistenceInterface
with CacheSessionPersistence
:
<?php // config/autoload/dependencies.global.php use App\Cache\CacheItemPoolFactory; use Psr\Cache\CacheItemPoolInterface; use Zend\Expressive\Session\Cache\CacheSessionPersistence; use Zend\Expressive\Session\SessionPersistenceInterface; return [ // ... 'aliases' => [ SessionPersistenceInterface::class => CacheSessionPersistence::class, ], 'factories' => [ CacheItemPoolInterface::class => CacheItemPoolFactory::class, ], // ... ];
If we need a custom configuration for zend-expressive-session-cache
, we can define at config/autoload/zend-expressive.global.php
:
<?php // config/autoload/zend-expressive.global.php use Psr\Cache\CacheItemPoolInterface; return [ // ... 'zend-expressive-session-cache' => [ 'cache_item_pool_service' => CacheItemPoolInterface::class, 'cookie_name' => 'PHPSESSION', 'cookie_path' => '/', 'cache_limiter' => 'nocache', 'cache_expire' => 10800, 'last_modified' => null, ], // ... ];
To start the session, we can apply Zend\Expressive\Session\SessionMiddleware
into config/pipeline.php
before Zend\Expressive\Router\Middleware\RouteMiddleware
registration:
<?php use Zend\Expressive\Router\Middleware\RouteMiddleware; use Zend\Expressive\Session\SessionMiddleware; // ... $app->pipe(SessionMiddleware::class); $app->pipe(RouteMiddleware::class); // ...
The preparation done! Now, we can use it by consume it from via SessionMiddleware, for example, we need to generate “csrf” token when rendering the form, like I written at the CSRF usage in Expressive post, we can just use the session as is, and the cache will be used as session persistence:
<?php // src/Handler/LoginPageHandler.php use Zend\Expressive\Session\SessionInterface; use Zend\Expressive\Csrf\SessionCsrfGuard; use Zend\Expressive\Session\SessionMiddleware; use Zend\Expressive\Csrf\CsrfMiddleware; // ... private function getToken(SessionInterface $session, SessionCsrfGuard $guard) { if (! $session->has('__csrf')) { return $guard->generateToken(); } return $session->get('__csrf'); } public function process( ServerRequestInterface $request, RequestHandlerInterface $handler ) : ResponseInterface { $guard = $request->getAttribute(CsrfMiddleware::GUARD_ATTRIBUTE); $loginForm = new LoginForm($guard); $session = $request->getAttribute(SessionMiddleware::SESSION_ATTRIBUTE); $token = $this->getToken($session, $guard); // ... } // ...
That’s it!
leave a comment