0

I'm looking for solution for override.

Magento\Framework\Session\SessionManager

I use the usually way (preference in di.xml), but no hope.

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">
    <preference for="Magento\Framework\Session\SessionManager" type="Gssi\FixEmptyCart\Session\SessionManager" />
</config>

SessionManager.php

<?php
/**
 * Magento session manager
 *
 * Copyright © 2013-2017 Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Gssi\FixEmptyCart\Session;

/**
 * Session Manager
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 */
class SessionManager extends \Magento\Framework\Session\SessionManager
{
    public function regenerateId()
    {
        var_dump('1234'); exit;
        if (headers_sent()) {
            return $this;
        }

        if ($this->isSessionExists()) {
            $oldSessionId = session_id();            
            session_regenerate_id();   //regen the session
            $new_session_id = session_id();

            $_SESSION['new_session_id'] = $new_session_id;

            // Set destroy timestamp
            $_SESSION['destroyed'] = time();

            // Write and close current session;
            session_commit();
            $oldSession = $_SESSION;   //called after destroy - see destroy!
            // Start session with new session ID
            session_id($new_session_id);
            ini_set('session.use_strict_mode', 0);
            session_start();
            ini_set('session.use_strict_mode', 1);
            $_SESSION = $oldSession;
            // New session does not need them
            unset($_SESSION['destroyed']);
            unset($_SESSION['new_session_id']);  
        } else {
            session_start();
        }
        $this->storage->init(isset($_SESSION) ? $_SESSION : []);

        if ($this->sessionConfig->getUseCookies()) {
            $this->clearSubDomainSessionCookie();
        }
        return $this;
    }

    public function start()
    {
        if (!$this->isSessionExists()) {
            \Magento\Framework\Profiler::start('session_start');

            try {
                $this->appState->getAreaCode();
            } catch (\Magento\Framework\Exception\LocalizedException $e) {
                throw new \Magento\Framework\Exception\SessionException(
                    new \Magento\Framework\Phrase(
                        'Area code not set: Area code must be set before starting a session.'
                    ),
                    $e
                );
            }

            // Need to apply the config options so they can be ready by session_start
            $this->initIniOptions();
            $this->registerSaveHandler();
            if (isset($_SESSION['new_session_id'])) {
             // Not fully expired yet. Could be lost cookie by unstable network.
             session_commit();
             session_id($_SESSION['new_session_id']);
             }
            // potential custom logic for session id (ex. switching between hosts)
            $this->setSessionId($this->sidResolver->getSid($this));
            session_start();
            if (isset($_SESSION['destroyed'])) {
               if ($_SESSION['destroyed'] < time()-300) {
                   $this->destroy(['clear_storage' => true]);

               }
            }
            $this->validator->validate($this);

            register_shutdown_function([$this, 'writeClose']);

            $this->_addHost();
            \Magento\Framework\Profiler::stop('session_start');
        }
        $this->storage->init(isset($_SESSION) ? $_SESSION : []);
        return $this;
    }
}
?>

I've also clear cache, enable this module, setup upgrade ..
Please help, thanks :)

2 Answers 2

0

Because many child classes extend Magento\Framework\Session\SessionManager

Magento used subclass of Magento\Framework\Session\SessionManager instead of Magento\Framework\Session\SessionManager such as

  • \Magento\Company\Model\Authorization\Session
  • \Magento\Customer\Model\Session

And objectManager Create Subclass not Magento\Framework\Session\SessionManager, You can try to override Magento\Customer\Model\Session.

in that bug, you should apply the path instead of trying to fix.

Link reference path file: https://github.com/magento/magento2/issues/12362#issuecomment-416065934

2
  • thanks, i'll try it later :) they override vendor/magento/module-checkout/Controller/Index/Index.php
    – fudu
    Commented Oct 12, 2018 at 10:40
  • Magento Override that controller too.
    – HoangHieu
    Commented Oct 12, 2018 at 13:59
0

So i've found the solution
My solution is based on Git command:
First, you create 2 .patch file in patches folder in magento root folder.
For example: My project named "magento_project". So the .patch file should be created in "htdocs/magento_project/patches/sessionmanager.patch"
Here is my patch file i've created for magento 2.1.10 to fix "empty cart" issue ( check the link to know how to fix "empty cart" issue)
https://github.com/magento/magento2/issues/12362

C:\xampp\htdocs\magento_project\patches\sessionmanager.patch

--- a/vendor/magento/framework/Session/SessionManager.php
+++ b/vendor/magento/framework/Session/SessionManager.php
@@ -468,12 +468,23 @@
         if ($this->isSessionExists()) {
-            $oldSessionId = session_id();
-            session_regenerate_id();
-            $newSessionId = session_id();
-            session_id($oldSessionIds);
-            session_destroy();
-
-            $oldSession = $_SESSION;
-            session_id($newSessionId);
-            session_start();
-            $_SESSION = $oldSession;
+            $oldSessionId = session_id();
+            session_regenerate_id();   //regen the session
+            $new_session_id = session_id();
+
+            $_SESSION['new_session_id'] = $new_session_id;
+
+            // Set destroy timestamp
+            $_SESSION['destroyed'] = time();
+
+            // Write and close current session;
+            session_commit();
+            $oldSession = $_SESSION;   //called after destroy - see destroy!
+            // Start session with new session ID
+            session_id($new_session_id);
+            ini_set('session.use_strict_mode', 0);
+            session_start();
+            ini_set('session.use_strict_mode', 1);
+            $_SESSION = $oldSession;
+            // New session does not need them
+            unset($_SESSION['destroyed']);
+            unset($_SESSION['new_session_id']);
         } else {
\ No newline at end of file

C:\xampp\htdocs\magento_project\patches\sessionmanager2.patch

--- a/vendor/magento/framework/Session/SessionManager.php
+++ b/vendor/magento/framework/Session/SessionManager.php
@@ -185,7 +185,19 @@
             $this->registerSaveHandler();

-            // potential custom logic for session id (ex. switching between hosts)
-            $this->setSessionId($this->sidResolver->getSid($this));
-            session_start();
-            $this->validator->validate($this);
+            if (isset($_SESSION['new_session_id'])) {
+             // Not fully expired yet. Could be lost cookie by unstable network.
+             session_commit();
+             session_id($_SESSION['new_session_id']);
+             }
+            // potential custom logic for session id (ex. switching between hosts)
+            $this->setSessionId($this->sidResolver->getSid($this));
+            session_start();
+            if (isset($_SESSION['destroyed'])) {
+               if ($_SESSION['destroyed'] < time()-300) {
+                   $this->destroy(['clear_storage' => true]);
+
+               }
+            }
+            $this->validator->validate($this);
+

             register_shutdown_function([$this, 'writeClose']);
\ No newline at end of file

Okay, the reason i created 2 file because when i put them in one file, it will cause an error patch fragment without header which i still dont know how to fix.
After create this 2 patch file, open command line in your magento root folder, which in mine case is "magento_project".
And type git apply patches/sessionmanager.patch and git apply patches/sessionmanager2.patch.
If you got error when running this command, and it say something about line 468 and line 185, it highly because of your SessionManager.php in your project is different than mine.
Please check again in patch file and change so it look like SessionManager.php in your project.
Oh, and dont forget to check the white space in patch file. Its really important. The white space of patch file is always = white space in SessionManager.php +1, accept for the line which have + and - at the beginning of the line.

That's it. Thanks for reading. Hope it help some one :)
Gonna update if i know something else

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.