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_close
或 session_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:在标头重定向之前会话未保存的主要内容,如果未能解决你的问题,请参考以下文章