在PHP中重新打开会话

在PHP中重新打开会话,php,apache,session,session-cookies,Php,Apache,Session,Session Cookies,如何在PHP中重新打开会话,而不会收到已发送的标题警告 在设置了我想要设置的所有会话变量之后,我用关闭会话。我这样做是因为只要会话是打开的,就可能只有一个来自同一客户机的活动连接。但我喜欢有多个平行的 但是,如果我想在以后设置另一个会话变量,我需要再次使用重新打开会话。这是可行的,但由于我已经向客户机发送了代码,所以它会打印“headers ready sent”-警告。为什么它要再次设置cookie?cookie已经设置好了。我唯一需要的是再次获得在服务器上写入会话文件的权限 嗯,我可以压制他

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

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

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

嗯,我可以压制他们。但是有没有一种方法可以重新打开一个会话,该会话在会话_write _close关闭时被关闭,而无需重新发送Cookie头?Cookie标头已由第一个会话\u 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();
?>

编辑查看@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();

这将防止php再次调用
php\u session\u send\u 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

您可以取消显示警告,但如果标头已发送,会话将不会启动。您需要在向浏览器输出任何内容之前启动会话,没有其他方法。否,会话将再次启动。它起作用了。这是因为第一个会话_start()已经发送了cookies,可以更好地构建应用程序流,这样您就可以首先完成会话中需要完成的所有工作。将内容输出到浏览器应该是您最后要做的事情;当您组装HTML时,您的所有业务逻辑都应该已经完成,并且在输出已经开始之后不需要写入会话。
我这样做,因为只要会话处于打开状态…
-仅当您在具有重文件锁定(即MSWindows)的机器上使用默认的基于文件的处理程序时。为什么不使用更好的会话处理程序呢?我不知道它与自定义会话处理程序会有所不同。也可以尝试一下。谢谢那就行了。但是我想我更喜欢只抑制警告,而不是使用输出缓冲,这会减慢内容到达客户端的速度。@JochenJung在这种情况下,您必须抑制警告。不能双向调用-因为
session\u start()
尝试设置标头,因此在标头发送后,如果不发出警告,则无法调用它。现在我在很大程度上同意你的观点,这是愚蠢的,这是不可能的,真正需要的是
session\u lock()
/
session\u unlock()
,它将释放会话文件,以便并发请求可以使用它,而不必再次发送头。不幸的是,这正是你所坚持的。@JochenJung我想另一个选择是“处理”不可避免的错误,但最终,像这样使用时,这只是一个更复杂的
@
操作符。我理解您希望不惜一切代价避免
@
(这是值得赞扬的),但在这种特殊情况下,我认为这是可以接受的。请确保您在代码中正确地注释它。@ JochenJung还考虑如果<代码> $ySudio是存储该信息的最佳位置-它是否可以登录到数据库?您存储的数据到底是什么?为什么不能在生成输出之前生成这些数据?这是一个有趣的想法。暂定+1,我将测试它。
ini\u集('session.cache\u limiter',null)添加-仍然未测试,但这也是一个与会话相关的http头。是的,第四个选项修复了它。这是一个有效的解决办法。(查看历史记录中的所有三项)我发现有必要保存会话id,如
$session\u id=session\u id()
(在
会话写入\u关闭()
之前),然后像
会话开始($session\u id)
那样使用它。否则,我重新打开的会话是空的。此外,我正在使用此技术定期重新打开会话,以检查用户是否仍在脚本中登录,以实现服务器发送的事件。这在php 7.2中不再起作用:(“session_start():头已发送时无法启动会话”
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