用PHP重新打开会话


Reopening a session in PHP

如何在PHP中重新打开会话,而不获取已发送警告的标头?

在设置了我喜欢设置的所有会话变量之后,我用session_write_close()关闭会话。我这样做是因为只要会话是打开的,同一客户端可能只有一个活动连接。但我喜欢多个平行的。

但是,如果我想在以后设置另一个会话变量,我需要再次使用session_start()重新打开会话。这是可行的,但由于我已经向客户端发送了代码,它会打印"已发送的头"-警告。它为什么要再次设置cookie?cookie已设置。我只需要再次获得在服务器上写入会话文件的权限。

好吧,我可以压制他们。但是,有没有一种方法可以重新打开用session_write_close关闭的会话,而不重新发送Cookie标头?Cookie标头已由第一个session_start()正确发送。因此,第二个只需要让我重新访问存储在web服务器上的会话文件。

<?php
session_start();
// setting all the session vars I like to set
session_write_close(); // <-- // To allow parallel requests by the same user, while this script is still running
// Code that takes some time to execute
// It also prints output, so no more cookie headers after this point
@session_start(); // <-- works, but I like to use it without suppressing warnings
$_SESSION['key'] = 'new value I like to store';
session_write_close();
?>
session_start();
...
session_write_close();
...
ini_set('session.use_only_cookies', false);
ini_set('session.use_cookies', false);
ini_set('session.use_trans_sid', false);
ini_set('session.cache_limiter', null);
session_start(); // second session_start

这将阻止php再次调用php_session_send_cookie()
看到它工作。

尽管重组脚本似乎仍然是更好的选择。。。


对于PHP7.2+,您基本上需要重新实现会话cookie以避免错误和警告:

ini_set('session.use_only_cookies', false);
ini_set('session.use_cookies', false);
ini_set('session.use_trans_sid', false);
ini_set('session.cache_limiter', null);
if(array_key_exists('PHPSESSID', $_COOKIE))
    session_id($_COOKIE['PHPSESSID']);
else {
    session_start();
    setcookie('PHPSESSID', session_id());
    session_write_close();
}
session_start();
...
session_write_close();
...
session_start(); // second session_start

EDIT查看@VolkerK的解决方案,它比这个更好。

只需在脚本执行时缓冲脚本的输出,以防止发送头,并在最后输出:

<?php
  session_start();
  // setting all the session vars I like to set
  session_write_close();
  // Start output buffer
  ob_start();
  // Code that takes some time to execute
  // Do session stuff at the end of the script
  session_start();
  $_SESSION['key'] = 'new value I like to store';
  session_write_close();
  // Send output to client
  ob_end_flush();

参考:输出控制功能