由于我没有找到为新窗口/标签打开新会话的任何重要解决方案,因此我考虑了以下似乎可行的解决方案:
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]
现在:
- 由于我正在序列化一个
$_SESSION
数组的 n 个副本(在[SubSession->]$SESSIONSTORE
数组中)并且
知道该$_SESSION
数组是使用不同的方法进行序列化和反序列化的,
所以当我反序列化它们时可能会出现一些问题? - 由于我没有说 php 以什么顺序调用
__destruct()
脚本末尾的方法,
我怎么能确定这个类将是最后一个被销毁的?
(当子会话²处于活动状态时,这可以防止某些其他自序列化¹将存储在“主”$_SESSION 上。
1:我使用自序列化一词来表示一个类,该类在被破坏之前在 $_SESSION 数组中的某个位置进行序列化 2:我打算使用 $_SESSION 数组从 中的位置复制的会话进行子会话,[SubSession->]$SESSIONSTORE
由创建$__SUB_SESSION->forkActive($subSessID);
并激活$__SUB_SESSION->activate($subSessID);