PHP:在标头重定向之前会话未保存

Posted

技术标签:

【中文标题】PHP:在标头重定向之前会话未保存【英文标题】:PHP: session isn't saving before header redirect 【发布时间】:2011-02-27 11:10:43 【问题描述】:

我已经阅读了这个问题的 php 手册,这似乎是一个很常见的问题,但我还没有找到解决方案。我正在将会话保存在数据库中。 我的代码如下:

// session
$_SESSION['userID'] = $user->id;        
header('Location: /subdirectory/index.php');

然后在 index.php 的顶部 session_start() 之后,我已经 var_dumped 全局 $_SESSION 并且用户 ID 不在其中。正如我所说,我查看了 PHP 手册 (http://php.net/manual/en/function.session-write-close.php),session_write_closesession_regenerate_id(true) 都没有为我工作。 有人知道解决方案吗?

编辑:我的文件顶部有 session_start()。当我在标头重定向之前对会话全局进行 var_dump 时,我在其中看到了用户 ID,但在另一个文件中没有,该文件位于此脚本的子目录中

【问题讨论】:

你在 session_starting() 进行重定向吗? 你确定 $user->id 设置了吗? 您好,请查看我为@ahmet2106 的帖子留下的评论 什么是 register_globals 状态? 【参考方案1】:

我知道这是一个老话题,但我找到了解决方案(对我来说)。 我在标题后面放了一个出口。

$_SESSION['session'] = 'this is a session';
header('location: apage.php');
exit;

这对我有用

【讨论】:

它只适用于同一个目录。如何为子目录做这项工作? F.e.: 从 http:/domain.com 到 http:/domain.com/subdir/ ?【参考方案2】:

@Matt(还不能发表评论...):如果: a) 它出现在重定向之前的会话中 b)其他键工作

80% 的时间问题是 register_globals,并且在某处使用了同名变量 $userID(另外 19% 只是在不期望的地方覆盖,1% 无法在重定向之前写入/锁定会话和陈旧的数据,在这种情况下,您可以在重定向之前尝试 session_write_close())。不用说 register_globals 应该关闭:P

【讨论】:

3 年后。 session_write_close 是今天最好的评论!【参考方案3】:

我没有听说过这个问题,但我没有太多使用会话。

对于会话,您必须做一些事情并进行一些设置:

在客户端启用 cookie session_start(),在任何事情发生之前 确保您不会破坏会话(除非他们想注销) PHP 会话 ID 必须相同(与 cookie 有关)

另一个问题可能是 $user->id 正在返回对下一页上不存在的对象的引用。很可能不会,但请确保。

如果我看到您的代码,我可以为您提供更多帮助。但是在调试时使用 session_id() 检查会话密钥并确保它是相同的。如果您可以尝试,请告诉我我可以继续提供帮助。

我也想知道当我重新参加会议时这会如何结束。

【讨论】:

【参考方案4】:

您应该在使用会话数组之前启动会话。

PHP 代码, session_start(); $_SESSION['userID'] = $user->id; header('位置:/subdirectory/index.php');

【讨论】:

【参考方案5】:

你有没有 session_start();在上面?

未经测试,但您不能这样做:

session_start();
$_SESSION['userID'] = $user->id;
if( $_SESSION['userID'] == $user->id )
  
    header('Location: /index.php');

我从来没有遇到过这个问题,很有趣

【讨论】:

是的,我愿意。当我在标头重定向之前 var_dump 会话全局时,它就在那里,只是当我转到原始脚本的子文件夹中的新文件时才不是 @Matt 很有趣,但它真的很有趣,因为应该设置会话,也许任何其他代码正在删除你的会话,你确定没有其他地方是 session_destroy(); ? 奇怪,我将 $_SESSION['userID'] 更改为 $_SESSION['uid'] 并且它按预期工作。我不知道为什么两个大写字母会有所不同。我也用 userId 尝试过,这也很好。关于它为什么不接受用户 ID 的任何想法?有两个大写字母,我很困惑【参考方案6】:

userID 没有任何关键字状态。

对我来说唯一的原因是 $_SESSION['userID'] 在某处被覆盖或删除。

确保在要添加/访问会话的所有文件中使用 session->start()。

一件重要的事情(可能不适用于您的情况)是,如果使用 cookie 处理会话,则可以使 cookie 只能在某些目录和该目录下的子目录下访问。 无论如何,在您的情况下,子目录将有权访问会话。

【讨论】:

【参考方案7】:

确保两个页面是相同的php版本 (php5、php4有时会话路径不同)

【讨论】:

【参考方案8】:

我最近遇到了同样的问题。我正在为学校编写一个定制的 MVC 网站,正如大家所说,start_session() 必须在第一行代码中编写。

我的问题是“session_start()”的位置。它必须是全局控制器的第一行,而不是视图的第一行。 $_SESSION 在控制器的文件中不可访问,因为它仅在服务器渲染视图时启动。

然后,我在 header('location: xxx.php') 调用之后使用 session_write_close() 来为下一个请求保留会话变量。

例如:

globalController.php:

//First line
session_start();
require_once('Model/Database.php');
require_once('Model/Shop/Client.php');
...

logonController.php:

...
//Users is validated and redirected.
$_SESSION['client'] = $client;
header('location: index.php');
session_write_close();

希望它能解决你的问题。

【讨论】:

【参考方案9】:

这很烦人,但我终于找到了解决办法。

config.php 我有: 包括'session.php';

在 session.php 的顶部,我有: session_start();

通过将 session_start() 移动到 config.php 文件的顶部,viola...

问题解决了!

【讨论】:

您已经解决了这个问题,真是太好了。我只是建议你在你的解决方案中更干净一点,这样它也能帮助其他读者。【参考方案10】:

除了使用exit 强制终止脚本之外,另一种选择是使用session_write_close 强制将更改写入会话存储。

但是,如果您的脚本正确终止,则不会发生这种情况。

As the documentation about session_write_close states:

结束当前会话并存储会话数据。

会话数据通常在脚本终止后存储 需要调用 session_write_close(),但由于会话数据被锁定 为了防止并发写入,只有一个脚本可以在会话上运行 随时。将框架集与会话一起使用时,您将 体验由于这种锁定而一一加载的帧。你可以 通过结束会话来减少加载所有帧所需的时间 会话变量的所有更改完成后。

在我的情况下,这只发生在使用Xdebug 进行调试时,当我多次触发同一个脚本并因此多个进程试图操纵同一个会话时。不知何故,会话无法再被解锁。

【讨论】:

以上是关于PHP:在标头重定向之前会话未保存的主要内容,如果未能解决你的问题,请参考以下文章

PHP标头重定向不起作用并停留在login.php上

PHP标头未重定向到感谢页面

PHP 保存会话值 - 然后标题重定向

标头重定向后PHP $_SESSION为空

输出消息后如何使用标头重定向到php中的另一个页面?

有一个 PHP 重定向到登录页面,而不是强制登录