20

如何在 PHP 中重新打开会话而不会收到标头已发送警告?

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

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

好吧,我可以压制他们。但是有没有办法重新打开一个会话,它已经用 session_write_close 关闭而不重新发送 Cookie-header?第一个 session_start() 已经正确发送了 Cookie-header。所以第二个只需要让我重新访问存储在 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();
?>
4

2 回答 2

25
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

这将防止 phpphp_session_send_cookie()再次调用。
看到它工作

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


对于 PHP 7.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
于 2012-09-07T09:37:39.240 回答
6

编辑参见@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();

参考:输出控制功能

于 2012-09-07T09:22:43.480 回答