I have a simple custom session storage where I want to save how many pages user has visited. I make an Ajax request to controller action on every page load which updates the custom foo
session. Environment is local (Magento 2.4.3-p2), sessions are stored in DB, caches disabled: block_html
, full_page
.
The issue is that the session update is very incosistent:
- sometimes the initial
foo
session data is not being set on page load (sessions cleared) - when initial
foo
data is set it then sometimes doesn't get updated on next page load (it should increment the pages visited)
Foo/Bar/etc/di.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Foo\Bar\Model\Session">
<arguments>
<argument name="storage" xsi:type="object">Foo\Bar\Model\Session\Storage</argument>
</arguments>
</type>
</config>
Foo/Bar/Model/Session.php
<?php
namespace Foo\Bar\Model;
class Session extends \Magento\Framework\Session\SessionManager
{
/**
* @var \Magento\Framework\Event\ManagerInterface
*/
protected \Magento\Framework\Event\ManagerInterface $_eventManager;
/**
* @param \Magento\Framework\App\Request\Http $request
* @param \Magento\Framework\Session\SidResolverInterface $sidResolver
* @param \Magento\Framework\Session\Config\ConfigInterface $sessionConfig
* @param \Magento\Framework\Session\SaveHandlerInterface $saveHandler
* @param \Magento\Framework\Session\ValidatorInterface $validator
* @param \Magento\Framework\Session\StorageInterface $storage
* @param \Magento\Framework\Stdlib\CookieManagerInterface $cookieManager
* @param \Magento\Framework\Stdlib\Cookie\CookieMetadataFactory $cookieMetadataFactory
* @param \Magento\Framework\App\State $appState
* @param \Magento\Framework\Event\ManagerInterface $eventManager
* @param \Magento\Framework\Session\SessionStartChecker|null $sessionStartChecker
*/
public function __construct(
\Magento\Framework\App\Request\Http $request,
\Magento\Framework\Session\SidResolverInterface $sidResolver,
\Magento\Framework\Session\Config\ConfigInterface $sessionConfig,
\Magento\Framework\Session\SaveHandlerInterface $saveHandler,
\Magento\Framework\Session\ValidatorInterface $validator,
\Magento\Framework\Session\StorageInterface $storage,
\Magento\Framework\Stdlib\CookieManagerInterface $cookieManager,
\Magento\Framework\Stdlib\Cookie\CookieMetadataFactory $cookieMetadataFactory,
\Magento\Framework\App\State $appState,
\Magento\Framework\Event\ManagerInterface $eventManager,
\Magento\Framework\Session\SessionStartChecker $sessionStartChecker = null
) {
$this->_eventManager = $eventManager;
parent::__construct(
$request,
$sidResolver,
$sessionConfig,
$saveHandler,
$validator,
$storage,
$cookieManager,
$cookieMetadataFactory,
$appState,
$sessionStartChecker
);
$this->_eventManager->dispatch(
'foo_session_init',
['foo_session' => $this]
);
}
/**
* @return void
*/
public function setPagesVisitedData()
{
$pagesVisited = $this->getPagesVisited();
if (empty($pagesVisited)) {
$pagesVisited = 1;
} else {
$pagesVisited = (int) $pagesVisited + 1;
}
$this->setPagesVisited($pagesVisited);
}
}
Foo/Bar/Model/Session/Storage.php
<?php
namespace Foo\Bar\Model\Session;
class Storage extends \Magento\Framework\Session\Storage
{
/**
* @param \Magento\Customer\Model\Config\Share $configShare
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
* @param string $namespace
* @param array $data
*
* @throws \Magento\Framework\Exception\LocalizedException
*/
public function __construct(
\Magento\Customer\Model\Config\Share $configShare,
\Magento\Store\Model\StoreManagerInterface $storeManager,
string $namespace = 'foo',
array $data = []
) {
if ($configShare->isWebsiteScope()) {
$namespace .= '_' . $storeManager->getWebsite()->getCode();
}
parent::__construct($namespace, $data);
}
}
Foo/Bar/Model/Controller/Index.php
<?php
namespace Foo\Bar\Controller;
class Index extends \Magento\Framework\App\Action\Action implements \Magento\Framework\App\Action\HttpPostActionInterface
{
/**
* @var \Foo\Bar\Model\Session
*/
protected \Foo\Bar\Model\Session $_fooSession;
/**
* @param \Magento\Framework\App\Action\Context $context
* @param \Foo\Bar\Model\Session $fooSession
*/
public function __construct(
\Magento\Framework\App\Action\Context $context,
\Foo\Bar\Model\Session $fooSession
) {
$this->_fooSession = $fooSession;
parent::__construct($context);
}
/**
* @return void
*/
public function execute()
{
$this->_fooSession->setPagesVisitedData();
}
}
Edit: Similar issue reported but I'm updating the session from Ajax so it's not related: Magento 2 custom sessions not consistent