Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/251.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP-每个选项卡的会话数_Php_Session_Tabs - Fatal编程技术网

PHP-每个选项卡的会话数

PHP-每个选项卡的会话数,php,session,tabs,Php,Session,Tabs,是否可以按浏览器选项卡创建会话 例如,用户在其浏览器中打开了两个选项卡: 表1和表2 在选项卡1中他有一个会话: $_SESSION['xxx'] = 'lorem'; 在选项卡2中,会话是: $_SESSION['xxx'] = 'ipsum'; 现在刷新时,我需要在活动选项卡中获取当前会话。例如,如果用户刷新选项卡2,我需要获取加载的选项卡2的$\u会话['xxx'],即“ipsum”。但是$\u会话['xxx']不应在选项卡1上更改 是否有任何选项可以保存每个选项卡的会话。如果没有,还

是否可以按浏览器选项卡创建会话

例如,用户在其浏览器中打开了两个选项卡: 表1表2

选项卡1中他有一个会话:

$_SESSION['xxx'] = 'lorem';
选项卡2中,会话是:

$_SESSION['xxx'] = 'ipsum';
现在刷新时,我需要在活动选项卡中获取当前会话。例如,如果用户刷新选项卡2,我需要获取加载的选项卡2的
$\u会话['xxx']
,即“ipsum”。但是
$\u会话['xxx']
不应在选项卡1上更改

是否有任何选项可以保存每个选项卡的会话。如果没有,还有什么其他选择来处理这个问题


谢谢你的帮助

PHP将会话ID存储在cookie中,cookie是针对每个客户端(浏览器),而不是选项卡。因此,没有简单易行的方法可以做到这一点。可以通过创建自己的会话处理程序来实现这一点,但它们更多的是黑客,而不是解决方案,因此具有自身的风险和复杂性。无论出于何种原因,您可能需要它,我确信有一种比会话拆分更好的体系结构解决方案。

我一直在网上搜寻这个问题的答案,但还没有找到令人满意的解决方案。我终于在JavaScript中找到了一些类似的东西

//generate a random ID, doesn't really matter how    
if(!sessionStorage.tab) {
    var max = 99999999;
    var min = 10000000;
    sessionStorage.tab = Math.floor(Math.random() * (max - min + 1) + min);
}

//set tab_id cookie before leaving page
window.addEventListener('beforeunload', function() {
    document.cookie = 'tab_id=' + sessionStorage.tab;
});
HTML5
sessionStorage
不在选项卡之间共享,因此我们可以在那里存储唯一的选项卡ID。在窗口上监听
beforeunload
事件会告诉我们要离开(并加载其他页面)。通过在离开前设置cookie,我们可以在新请求中包含我们的值,而无需任何额外的URL操作。要区分选项卡,只需在服务器上选中
$\u COOKIE['tab\u id']
,并适当存储会话值

请注意,Firefox的行为很奇怪,因为触发
窗口。open()
将创建一个与其父级共享
会话存储的窗口,为您提供两个具有相同ID的选项卡。手动打开空白选项卡,然后导航到目标URL将为您提供单独的存储空间。到目前为止,Chrome在我所有的测试中都适用


我意识到这可能不是正确的答案,甚至不是一个“好”的答案,但这是一个答案。

我一直在尝试使用此功能制作一个web应用程序

它还没有成熟,并且有约束和流,比如如果您的javascript根据它向外部php代码发送帖子,就必须在url中传输会话id,但它是功能性的,适合我的需要(目前)

我正在考虑一个更安全的解决方案,所以请根据您的需要调整它,并给我您的建议

<?php
/**
* Split $_SESSION by browser Tab emulator.
* methods exemples are used whith :
* $session = new SessionSplit();
* as SessionSplit may reload the page, it has to be used on top of the code.
* 
*/
class SessionSplit{
    public $id;
    private $gprefix="session_slice_";
    private $prefix="";
    private $witness="";
    function SessionSplit($witness='witness'){
        if(session_status()===PHP_SESSION_NONE){
            session_start();
        }
        $this->witness=$witness;
        if($this->get_id()){
            $this->prefix=$this->gprefix.$this->id;
            //set a witness to 'register' the session id
            $this->set($this->witness,'true');
        }else{
            // force the session id in the url to not interfere with form validation
            $actual_link = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
            $new_link = $actual_link.(strpos($actual_link,'?')===false?'?':'&').
                'session_id='.$this->id;
            header('Location: '.$new_link); 
        }
    }
    private function get_id(){
        if(isset($_GET['session_id'])){
            $this->id=$_GET['session_id'];
            return true;
        }else{
            $this->new_id();
            return false;
        }
    }
    private function new_id(){
        $id=0;
        while(isset($_SESSION[$this->gprefix.$id.'.'.$this->witness])){$id++;}
        $this->id=$id;
    }
    // ----------- publics
    public function clearAll(){
        foreach($_SESSION as $key=>$value){
            if(strpos($key,$this->prefix.'.')===0){
                unset($_SESSION[$key]);
            }
        }
    }
    /**
    * $is_user=$session->has('user');
    * equivalent to
    * $is_user=isset($_SESSION['user']);
    * @param {string} $local_id 
    * @return {boolean}
    */
    public function has($local_id){
        return isset($_SESSION[$this->prefix.'.'.$local_id]);
    }
    /**
    * 
    * $session->clear('user');
    * equivalent to
    * unset($_SESSION['user']);
    * @param {string} $local_id 
    */
    public function clear($local_id){
        unset($_SESSION[$this->prefix.'.'.$local_id]);
    }
    /**
    * $user=$session->get('user');
    * equivalent to
    * $user=$_SESSION['user'];
    * @param {string} $local_id 
    * @return {mixed}
    */
    public function get($local_id){
        if (isset($_SESSION[$this->prefix.'.'.$local_id])) {
            return $_SESSION[$this->prefix.'.'.$local_id];
        }else return null;
    }
    /**
    * $session->set('user',$user);
    * equivalent to
    * $_SESSION['user']=$user;
    * @param {string} $local_id 
    * @param {mixed} $value
    */
    public function set($local_id,$value){
        $_SESSION[$this->prefix.'.'.$local_id]=$value;
    }
};
?>

这是我的解决方案;我们使用它来允许每个客户端打开多个应用程序视图

发布以获取数据: “doStuff=getData&model=GTD&sn=6789&type=random&date=2018年12月18日”

然后,控制器从表中获取数据,为设备构建对象,将其存储到会话对象,并将其存储在变量中。它生成每个选项卡的guid,以便用户可以将同一仪器与UI中的不同视图进行比较

$\会话[$model][$sn][$type][$guid][$key]

当然,guid也会发送回数据对象,以便选项卡知道以后如何调用该数据

当用户想要将结果打印到文件(pdf等)时,它会发送一篇文章,其中包含文章中的相关数据

'doStuff=saveFile&model=GTD&sn=6789&type=random&calDate=2018年12月18日&guid=randomKey'

然后,控制器将其传递到存储器以进行检索

会话类文件示例:

<?php
class Session {
public $fieldKey1;
public $fieldKey2;

public function GetStorage($model, $sn, $type, $guid, $key) {
    return $_SESSION[$model][$sn][$type][$guid][$key];
}

}

?>

控制器文件:

<?php
require_once('session.php'); 
global $session; //from session class file
switch($_POST['doStuff']) {
  case 'saveFile':
     $session->GetStorage($_POST['model'], $_POST['sn'], $_POST['type'], $_POST['guid'], $key);
     break;
}
?>


这允许用户拥有相同数据的多个视图,而无需覆盖每个选项卡中的数据集。如果每个选项卡不需要那么多的数据粒度,当然可以简化$\u会话变量的键数。

按选项卡,您指的是浏览器选项卡,对吗?这非常类似于这个问题:您可以在那里找到答案。我面临这个问题,我使用类似于
$\u会话['xxx']['uniquevalue']
,但我的运气是我用它来处理提交表单,所以我可以添加一个具有唯一值的唯一隐藏字段。。。。duno我的方法是否可以接受,但是否有效……)是的,我用url参数做的:)谢谢你的回答@Auris,当您打开多个窗口时,这是一个很好的用途。一个有新闻,另一个有Facebook,第三个有需要登录的出色应用程序。使用普通会话cookie,您可以登录,然后关闭该选项卡/窗口。但由于其他选项卡/窗口仍处于打开状态,因此会话仍处于活动状态。您可以重新打开新的选项卡/窗口,无需登录。我认为当应用程序窗口关闭时,会话终止,从而强制重新登录会更好。对于普通会话cookie,会话直到所有窗口都关闭后才会终止。@UncaAlby Hi,会话实际上在关闭窗口时终止,只要在cookie未过期的情况下再次打开时使用cookie中存储的id重新生成会话即可。然而,这不是问题的重点。Ihuber希望在不同的选项卡中为同一实体设置两个单独的会话。这是clinet功能,在服务器端并没有“干净”的方法来实现这一点。在您的示例中,您使用了3个不同的应用程序。这些应用程序有自己的会话实体,彼此无法访问(例如,您的超级应用程序无法管理FB会话容器-web security 101中的变量)。是的,这可能会起作用,但同样,这是一种黑客行为。如果你正在构建一些个人的东西并使用它,这是很好的,但是如果你正在构建一个propper商业产品,并且有人审查了你的代码,那么你很可能会因此而被解雇。您正在将基于应用程序的会话存储在选项卡id下,这意味着在公用计算机上,打开该选项卡id的任何人都可以使用您的会话。此外,如果用户以不同的选项卡顺序加载具有不同会话的应用程序组件,该怎么办就像我说的,这很好