如何使每个PHP脚本实例的会话变量唯一?

4

假设我有一个PHP脚本,其中包含一些选择框,我想将所选值存储在会话数组中。到目前为止,我使用以下结构将值分配给我的会话数组:

$_SESSION[SCRIPT_NAME]['filter_data']

SCRIPT_NAME是一个常量,用于存储脚本名称,这样可以使每个PHP脚本的会话变量唯一。一切都很好,直到用户在两个或更多标签中同时打开同一个脚本。在这种情况下,变量混合在一起,事情就会出错...

也许你有任何想法如何使每个脚本实例的会话变量绝对唯一?或者有什么建议可以以不同的方式实现功能?

我知道,我可以在URL中传递我的变量,但我不喜欢这个选项。我想使用会话,并且希望我的Web应用程序的每个脚本在整个用户登录会话期间记住用户的选择。


4
过滤器等应该放在URL中。如果它们不在那里,我怎么能够收藏一个结果或者给另一个人发送一个链接呢? - Matti Virkkunen
这取决于您使用会话存储的目的。首先,您应该尊重HTTP请求的幂等性。如果可以合理地在URL中传输它,则应该这样做。不应该有隐藏状态。 - deceze
嗯,Matti,这是我方法的一个缺点。但由于它不是公共网站,而是组织的内部Web应用程序,更重要的是在工作时记住过滤器。 - Georgy Nemtsov
我同意这里的其他评论 - 将过滤器放在URL中,而不是会话中。然后您将不会与多个浏览器返回会话cookie的问题作斗争。 - Ray Paseur
2
@Georgiy:这是一个内部应用程序并不意味着它可以让人们使用起来感到烦恼。人们经常使用网络,并且期望网站/应用程序以某种方式运行,无论是“内部”的还是其他的。 - Matti Virkkunen
@Matti:我想你是对的,最好的方法是将URL和会话结合起来。如果URL变量为空,则从会话中获取值,否则从URL中获取值。 - Georgy Nemtsov
6个回答

3

"...如何使每个脚本实例的会话变量绝对唯一?"

基本上答案是“你无法做到”。这是因为浏览器的所有实例(窗口和标签)共享同一个cookie存储。因此,两个实例返回相同的cookie并连接到同一个会话。在“现实生活”中很少出现问题,但它让开发人员感到疯狂,正如你现在所看到的那样;-)


你可以做到这个,看看我的答案。 - Petr

0
 <?php
        //Start session
        session_start();
        //Check whether the session variable SESS_MEMBER_ID is present or not
        if (!isset($_SESSION['id']) || ($_SESSION['id'] == '')) {
            header("location: index.php");
            exit();
        }

        $session_id=$_SESSION['id'];
        ?>

和文件连接

 <?php

 class DbConnector {

 var $theQuery;
 var $link;

 function DbConnector(){

    // Get the main settings from the array we just loaded
    $host = 'localhost';
    $db = '';
    $user = 'root';
    $pass = '';

    // Connect to the database
    $this->link = mysql_connect($host, $user, $pass);
    mysql_select_db($db);
    register_shutdown_function(array(&$this, 'close'));

}

   //*** Function: query, Purpose: Execute a database query ***
function query($query) {

    $this->theQuery = $query;
    return mysql_query($query, $this->link);

}

//*** Function: fetchArray, Purpose: Get array of query results ***
function fetchArray($result) {

    return mysql_fetch_array($result);

}

//*** Function: close, Purpose: Close the connection ***
function close() {

    mysql_close($this->link);

}

}

?>

请注意,仅提供代码答案是不被鼓励的。最好在周围加上一些文本解释! - GhostCat

0
  • 为每个打开的页面生成一个唯一标识符
  • 通过 get 方法将该唯一标识符传递给脚本
  • 使用该唯一标识符代替脚本名称

此方法存在的问题

如果您不清除未使用的会话变量,并且用户在会话过期之前频繁打开您的网站,则使用此方法存储的会话变量可能会随着时间的推移占用非常多的空间。

解决这些问题的方法

  • 为每个生成的唯一标识符存储一个时间戳
  • 每当用户在使用该唯一标识符的页面上执行操作时,将该时间戳更改为当前时间戳
  • 如果用户在具有其他唯一标识符的页面上执行动作,并且自上次动作以来经过了 x 时间,则删除它

*:可以在页面上执行的操作和页面刷新


0

这是一个非常古老的问题,但我写下来是为了其他程序员或初学者朋友们的使用。

只需为每个客户端请求设置一个验证页面以检查会话变量。 例如:valid_ref.php 或者在源代码中使用一个引用页面,并根据客户端请求在引用页面中调用其他页面。例如:index.php、home.php 或 ref.php 在 valid_ref.php 中检查 $_SESSION[SCRIPT_NAME]['filter_data'] 是否在会话中,当客户端打开新标签页时,您的 Web 应用程序将使用 $_SESSION[SCRIPT_NAME]['filter_data'] 中的上一次数据,这样您就不必担心来自同一客户端的浏览器中的新标签页问题。


0

您可以使用session_name($unique_script_instance_name)来完成此操作 - https://www.php.net/manual/zh/function.session-name.php

您所需要做的就是为脚本的每个实例定义一个唯一的名称。例如,如果您在共享服务器上有2个独立的应用程序安装,则为其中一个提供名称A,为第二个提供名称B,您可以将此值存储为$unique_script_instance_name

然后,在调用session_start()之前,您需要调用session_name()

// One script
$unique_script_instance_name "A";
session_name($unique_script_instance_name);
session_start();

...

// Second script
$unique_script_instance_name "B";
session_name($unique_script_instance_name);
session_start();

...

那样两个脚本将拥有自己的会话“域”,并且彼此之间会被隔离。那样

0

请记住,会话只是一个变量。您绝对可以为每个页面创建一个唯一的会话变量。对于每个获取请求,都将创建一个新的唯一会话变量。您需要做的就是创建唯一的会话名称。

<?php
 session_start();
 $_SESSION[$_GET['pid'].'_p1'] = "a session value";
 $_SESSION[$_GET['pid'].'_p2'] = "a session value";
 $_SESSION[$_GET['pid'].'_p3'] = "a session value";
?>

例如,如果您访问http://example.com/?pid=1232
会话名称将类似于$_SESSION['1232_p1']; 每个GET请求都会创建一个新的唯一会话。
要查看所有会话变量,请在页面末尾使用此代码:
<?php
echo '<pre>';
print_r($_SESSION);
echo '</pre>';
?>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接