【问题标题】:PHP5.4 "parse_str" behaving unexpectedlyPHP5.4“parse_str”行为异常
【发布时间】:2014-11-15 14:46:17
【问题描述】:

我正在使用 Zend Framework 2 的 AbstractRestfulController 在我们的项目中实现一个 CRUD API。使用 PUT HTTP 方法调用更新现有实体的逻辑。

当接收到一个 PUT 请求时,AbstractRestfulController 使用 PHP 的 parse_str 函数将请求体转换为一个数组,但是这个函数并没有做它应该做的事情。

因为它给了我奇怪的结果,我用 PHP 文档中提供的示例数据尝试了parse_str

// sample data from the PHP docs
$content = "first=value&arr[]=foo+bar&arr[]=baz";

// put the parsed variables into $parsedParams
parse_str($content, $parsedParams);

var_dumping $parsedParams 给了我以下信息

array(5) { 
    ["first"]=> string(1) "v" 
    ["lue"]=> string(0) "" 
    ["rr"]=> array(2) { 
        [0]=> string(5) "foo b" 
        [1]=> string(1) "b" 
    } 
    ["r"]=> string(0) "" 
    ["z"]=> string(0) "" 
} 

显然字符“a”让parse_str 感到困惑,但我完全不知道是什么导致了这种奇怪的行为。 PHP 文件的编码为 UTF-8,服务器在 Vagrant 环境中运行 Ubuntu 14.04,PHP 5.4 作为 Apache 2.4 模块。

这可能是什么原因?我阅读了有关 HTML 实体 & 而不是普通的 & 的问题,但这似乎不适用于此处。

更新

我刚刚在命令行中通过SSHing 在 Vagrant 机器中以交互模式运行了相同的代码。在交互模式下parse_str 可以正常工作!然后我通过$ php /var/www/test.php 从命令行运行我的测试脚本,它也可以正常工作。 这是 Apache PHP 模块或配置的问题吗?

【问题讨论】:

  • 刚刚用 PHP v5.4 试了一下,没有任何问题。也许您的字符串包含使 PHP 窒息的不可见字符?你可以试试echo strlen($content) 看看你得到了什么?
  • 复制了你发布的那个。 codepad.viper-7.com/FYbCCx 看起来不错
  • strlen($content) 给了我 35 的长度,这是正确的,可能是我的 PHP 版本的问题还是类似的问题?
  • 我现在在命令行的交互模式下尝试了与上面相同的代码,我已将我的发现添加到最初的问题中

标签: php php-5.4


【解决方案1】:

注意&a 上的字符串是如何拆分的?

我认为配置设置arg_separator.input 被错误地设置为"&" 而不是默认的"&"

可以在php.ini.htaccesshttpd.conf.user.ini 中设置此设置。见:Where a configuration setting may be set

测试程序:

<?php

  echo "arg_separator.input = '", ini_get ('arg_separator.input'), "'\n";

  $content = "first=value&arr[]=foo+bar&arr[]=baz";
  parse_str($content, $parsedParams);

  var_dump ($parsedParams);

php.ini 中不同设置的输出(有些压缩):

arg_separator.input = '&'
array(2) {
  ["first"] => string(5) "value"
  ["arr"] => array(2) {
    [0] => string(7) "foo bar"
    [1] => string(3) "baz"
  }
}
arg_separator.input = '&amp;'
array(5) {
  ["first"] => string(1) "v"
  ["lue"] => string(0) ""
  ["rr"] => array(2) {
    [0] => string(5) "foo b"
    [1] => string(1) "b"
  }
  ["r"] => string(0) ""
  ["z"] => string(0) ""
}

配置设置arg_separator.<b>output</b> 也默认为"&amp;"。将此设置为"&amp;amp;" 可能 如果您 生成 HTML 输出就可以了。但是,如果您想使用http_build_query() 来生成 HTTP Location: 标头,或者在 HTML 实体引用不适合的其他情况下,您将遇到麻烦。

测试程序:

<?php

  echo "arg_separator.output = '", ini_get ('arg_separator.output'), "'\n";

  $q = http_build_query (array ('a' => 0, 'b' => 1, 'c' => 2));
  echo $q, "\n";

php.ini 中不同设置的输出:

arg_separator.output = '&'
a=0&b=1&c=2
arg_separator.output = '&amp;'
a=0&amp;b=1&amp;c=2

【讨论】:

  • 非常感谢,这是导致问题的原因!我自己要花几年时间才能弄清楚这一点。在设置 Vagrant 环境时,我将 php.ini 从我们的生产服务器(共享环境)复制到 Vagrant 机器,我想我也必须在生产服务器上注意这个问题。我可以安全地将 arg_seperator.output 保留为“&”吗虽然?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-05
  • 2017-01-22
  • 2013-04-14
  • 2014-01-29
  • 1970-01-01
相关资源
最近更新 更多