如果我将感叹号放入变量名中,PHP 的行为会很奇怪

Posted

技术标签:

【中文标题】如果我将感叹号放入变量名中,PHP 的行为会很奇怪【英文标题】:Weird PHP behavior if I put exclamation point into variable name 【发布时间】:2011-03-30 01:17:58 【问题描述】:

php 本身有我见过的最奇怪的问题。

设置:

IIS 下的 PHP 5.33(也试过 PHP 5.2.14)

问题: 一旦我将感叹号放入会话数组中的键中,PHP 就会删除所有会话数据。

示例:

session1.php

session_start();
$_SESSION["foo"] = 'test';
header('Location: session2.php');

session2.php

session_start();
var_dump($_SESSION);
die();

工作正常,我看到打印出可变数据。

array(1)  ["foo"]=>  &string(4) "test"  

但是如果我将第一个文件中的行更改为

$_SESSION["foo!"] = 'test'; 

$_SESSION["f!oo"] = 'test'; 

我的意思是如果我添加感叹号 - 那么当我到达第二个文件时 $_SESSION 数组是空的

array(0)   

当我在 5.2.14 上时,我认为这是一个错误的 PHP 版本,但升级没有帮助。 我什至不知道问题可能是什么。也许这与 Windows 设置或 IIS 有关?

有什么想法吗?

【问题讨论】:

您使用的是什么会话后端?普通文件? session.save_handler=files 我的 php 5.3.1 与 "!" 配合得很好(xampp)。 有一个旧的错误报告,但显然它无法重现 (bugs.php.net/bug.php?id=14160) 【参考方案1】:

那么你的问题是什么?这个错误的原因是什么或如何避免它? 第一个可能是因为一些奇怪的 PHP 内部结构。例如,您不能使用具有相同结果的数字键。 后一个更简单 - 不要将感叹号放入会话数组中的键中。

我记得,PHP 会话机制来自 PHPLib - 有史以来第一个 PHP 框架。由一些志愿学生撰写。不是一个非常理想的。一旦在 4.0 版本中添加到 PHP 中,只能在 4.1 版本中使用,但仍然有一些奇怪的遗留问题,比如 register_globals 支持。后一个很可能是您的问题的原因。 $_SESSION 数组键必须是有效的 PHP 变量名,以实现古老的 register_globals 行为,即会话变量成为全局 PHP 变量。

【讨论】:

register_globals 在 5.3 中已被弃用。 cbglum 使用的是 5.3.3 在注意到问题后,我首先关闭了 register_globals。现在我更加确信这更多的是 IIS 或 Win 问题,但我不知道如何在不离开此服务器的情况下解决此问题。有什么提示吗? @cbglum 如果我猜对了,这不是 setting 问题,而是 PHP 核心代码问题。通过更改设置,您不会更改代码本身,它保持不变。所有的错误都完好无损。我已经告诉过你一个提示:不要使用!在密钥名称中标记。至少再深一层,$_SESSION["cart"]["f!oo"] = 'test';,但我还是不明白你为什么坚持用这个奇怪的名字【参考方案2】:

不是 Windows,它不是 Apache 或任何其他网络服务器,它是 PHP 核心。

我看了一下 - 从 5.3 到 5.6,问题仍然存在:你不能有一个“!” (感叹号)或“|” (管道)在会话密钥中。

Suhosin 补丁将部分修复它。然后,您可以在钥匙内的任何位置有一个感叹号,但不能在第一个位置,所以“foo!”是允许的,但不是“!foo”。管道仍然被禁止。

修复:

    将 php.ini 中的 session.serialize_handler 更改为 php_binaryphp_serialize 重启网络服务器。

玩得开心!

【讨论】:

以上是关于如果我将感叹号放入变量名中,PHP 的行为会很奇怪的主要内容,如果未能解决你的问题,请参考以下文章

PHP PHP变量名中的变量

PHP变量名中的变量

传递包含“!!!!”的字符串时 argv 的奇怪行为

firebase 存储 cors 奇怪的行为

奇怪的 UIContainerView 自动布局旋转行为

奇怪的行为:从堆栈拖动到状态项不起作用