0

由于我没有找到为新窗口/标签打开新会话的任何重要解决方案,因此我考虑了以下似乎可行的解决方案:

1-创建了一个类似的单例类“SubSession”

<?php

/**
 * Provides a data structure and routines to be able to create and/or
 * activate a subSession
 * @author Roberto CASULA (casual4free@gmail.com)
 */
final class SubSession {
   private static $instance = NULL;

   private $current_active_name = 'MAIN';
   private $SESSIONSTORE = array();

   private $MAIN_SESSION;

   private function currentSessionStore() {
      $active_name = $this->current_active_name;
      $this->SESSIONSTORE[$active_name] = $_SESSION;
   }
   private function mainSessionStore() {
      $active_name = $this->current_active_name;
      if($active_name !== 'MAIN')
         throw new BadMethodCallException(__CLASS__.': the current active subSession is not MAIN');
      $this->MAIN_SESSION = $_SESSION;
   }

   public function exists($name) {
      return array_key_exists($name, $this->SESSIONSTORE);
   }

   public function forkActive($name) {

      if( $this->exists($name) )
         throw new InvalidArgumentException(__CLASS__.": $name yet exists");

      $this->SESSIONSTORE[$name] = $_SESSION;
   }

   public function activate($name) {
      $active_name = $this->current_active_name;

      if($name === $active_name) return 'yet_active';

      if($name == 'MAIN') :
         $this->currentSessionStore();
         $_SESSION = $this->MAIN_SESSION;
         $this->current_active_name = $name;
         return TRUE;

      elseif( $this->exists($name) ) :
         $this->mainSessionStore();
         $_SESSION = $this->SESSIONSTORE[$name];
         $this->current_active_name = $name;
         return TRUE;

      else :
         throw new InvalidArgumentException('The searched name do not exists: '.$name);

      endif;
   }

   public function __get($name) {
      switch ($name) {
         case 'MAIN_SESSION' :
            if($this->current_active_name === 'MAIN')
               return $_SESSION;
         default :
            return $$name;
      }
   }

   private function __construct() {}

   public function __wakeup() {}

   public function __sleep() {
      return array('SESSIONSTORE');
   }

   public function __destruct() {
      $this->activate('MAIN');
      $_SESSION[__CLASS__] = serialize($this);
   }
   /**
    * 
    * @return SubSession
    */
   public static function getInstance() {

      if( self::$instance !== NULL) :
         return self::$instance;

      elseif( isset($_SESSION[__CLASS__]) ) :
         return self::$instance = unserialize($_SESSION[__CLASS__]);

      else :
         return self::$instance = new self();

      endif;      
   }

}

2-在“session_start();”之后添加了以下行

$__SUB_SESSION = SubSession::getInstance();

if( isset($_GET['sub_session_id']) ) {
   $subSessID = $_GET['sub_session_id'];

   if( !$__SUB_SESSION->exists($subSessID) )
      $__SUB_SESSION->forkActive($subSessID);

   $__SUB_SESSION->activate($subSessID);
}

3-在 .htaccess 中创建了一个条目

RewriteRule ^@sub_session_id=([^/]+)(.*)$ $2?sub_session_id=$1 [QSA]

现在:

  1. 由于我正在序列化一个$_SESSION数组的 n 个副本(在[SubSession->]$SESSIONSTORE数组中)并且
    知道该$_SESSION数组是使用不同的方法进行序列化和反序列化的,
    所以当我反序列化它们时可能会出现一些问题?

  2. 由于我没有说 php 以什么顺序调用__destruct()脚本末尾的方法,
    我怎么能确定这个类将是最后一个被销毁的?
    (当子会话²处于活动状态时,这可以防止某些其他自序列化¹将存储在“主”$_SESSION 上。

1:我使用自序列化一词来表示一个类,该类在被破坏之前在 $_SESSION 数组中的某个位置进行序列化 2:我打算使用 $_SESSION 数组从 中的位置复制的会话进行子会话,[SubSession->]$SESSIONSTORE由创建$__SUB_SESSION->forkActive($subSessID);并激活$__SUB_SESSION->activate($subSessID);

4

0 回答 0