如果我.
通过$ _GET PHP在其名称中传递PHP变量,则自动用_
字符替换它们.例如:
<?php
echo "url is ".$_SERVER['REQUEST_URI']."<p>";
echo "x.y is ".$_GET['x.y'].".<p>";
echo "x_y is ".$_GET['x_y'].".<p>";
Run Code Online (Sandbox Code Playgroud)
...输出以下内容:
url is /SpShipTool/php/testGetUrl.php?x.y=a.b
x.y is .
x_y is a.b.
Run Code Online (Sandbox Code Playgroud)
......我的问题是这样的:有什么方法可以阻止它吗?不能为我的生活弄清楚我做了什么值得这样做
我运行的PHP版本是5.2.4-2ubuntu5.3.
Jer*_*ten 63
这是PHP.net对其原因的解释:
输入变量名称中的点
通常,PHP在传递到脚本时不会更改变量的名称.但是,应该注意,点(句点,句号)不是PHP变量名中的有效字符.出于这个原因,看看它:
Run Code Online (Sandbox Code Playgroud)<?php $varname.ext; /* invalid variable name */ ?>
现在,解析器看到的是一个名为$ varname的变量,后跟字符串连接运算符,后跟barestring(即不带引号的字符串,它与任何已知的密钥或保留字不匹配)'ext'.显然,这没有预期的结果.
因此,请务必注意PHP会自动使用下划线替换传入变量名中的任何点.
那是来自http://ca.php.net/variables.external.
此外,根据此评论,这些其他字符将转换为下划线:
PHP转换为_(下划线)的字段名称字符的完整列表如下(不仅仅是点):
- chr(32)()(空格)
- chr(46)(.)(点)
- chr(91)([)(空方括号)
- chr(128) - chr(159)(各种)
因此看起来你已经坚持使用它,所以你必须使用dawnerd的建议将下划线转换回脚本中的点(我只是使用str_replace.)
crb*_*crb 58
很久以来一直回答问题,但实际上有更好的答案(或解决方法).PHP允许您处理原始输入流,因此您可以执行以下操作:
$query_string = file_get_contents('php://input');
Run Code Online (Sandbox Code Playgroud)
这将为您提供查询字符串格式的$ _POST数组,它们应该是句点.
然后,如果需要,您可以解析它(根据POSTer的评论)
<?php
// Function to fix up PHP's messing up input containing dots, etc.
// `$source` can be either 'POST' or 'GET'
function getRealInput($source) {
$pairs = explode("&", $source == 'POST' ? file_get_contents("php://input") : $_SERVER['QUERY_STRING']);
$vars = array();
foreach ($pairs as $pair) {
$nv = explode("=", $pair);
$name = urldecode($nv[0]);
$value = urldecode($nv[1]);
$vars[$name] = $value;
}
return $vars;
}
// Wrapper functions specifically for GET and POST:
function getRealGET() { return getRealInput('GET'); }
function getRealPOST() { return getRealInput('POST'); }
?>
Run Code Online (Sandbox Code Playgroud)
对于包含'.'的OpenID参数非常有用.和'_',每个都有一定的意义!
sci*_*lot 26
在上面的评论中突出显示Johan的实际答案 - 我只是将我的整个帖子包装在顶级数组中,完全绕过问题而不需要繁重的处理.
在你做的形式
<input name="data[database.username]">
<input name="data[database.password]">
<input name="data[something.else.really.deep]">
Run Code Online (Sandbox Code Playgroud)
代替
<input name="database.username">
<input name="database.password">
<input name="something.else.really.deep">
Run Code Online (Sandbox Code Playgroud)
并在邮政处理程序中,只需打开它:
$posdata = $_POST['data'];
Run Code Online (Sandbox Code Playgroud)
对我而言,这是一个两线的变化,因为我的观点完全是模板化的.
仅供参考.我在字段名称中使用点来编辑分组数据的树.
Rok*_*alj 18
这个功能的工作是我在2013年暑假期间提出的一个天才黑客.我有一天会写一篇关于它的博客文章.
例如,此修复程序通用并且具有深度阵列支持a.a[x][b.a]=10
.它parse_str()
在幕后使用一些预处理.
function fix($source) {
$source = preg_replace_callback(
'/(^|(?<=&))[^=[&]+/',
function($key) { return bin2hex(urldecode($key[0])); },
$source
);
parse_str($source, $post);
$result = array();
foreach ($post as $key => $val) {
$result[hex2bin($key)] = $val;
}
return $result;
}
Run Code Online (Sandbox Code Playgroud)
然后你可以像这样调用这个函数,具体取决于来源:
$_POST = fix(file_get_contents('php://input'));
$_GET = fix($_SERVER['QUERY_STRING']);
$_COOKIE = fix($_SERVER['HTTP_COOKIE']);
Run Code Online (Sandbox Code Playgroud)
对于低于5.4 PHP:使用base64_encode
代替bin2hex
和base64_decode
代替的hex2bin
.
发生这种情况是因为句点是变量名称中的无效字符,其原因在于PHP的实现非常深入,因此没有简单的修复(尚未).
在此期间,您可以通过以下方式解决此问题:
php://input
POST数据或$_SERVER['QUERY_STRING']
GET数据访问原始查询数据下面的转换函数(PHP> = 5.4)将每个键值对的名称编码为十六进制表示,然后执行常规parse_str()
; 完成后,它会将十六进制名称恢复为原始形式:
function parse_qs($data)
{
$data = preg_replace_callback('/(?:^|(?<=&))[^=[]+/', function($match) {
return bin2hex(urldecode($match[0]));
}, $data);
parse_str($data, $values);
return array_combine(array_map('hex2bin', array_keys($values)), $values);
}
// work with the raw query string
$data = parse_qs($_SERVER['QUERY_STRING']);
Run Code Online (Sandbox Code Playgroud)
要么:
// handle posted data (this only works with application/x-www-form-urlencoded)
$data = parse_qs(file_get_contents('php://input'));
Run Code Online (Sandbox Code Playgroud)
这种方法是Rok Kralj的改进版本,但需要进行一些调整,以提高效率(避免不必要的回调,对未受影响的键进行编码和解码)并正确处理数组键.
public function fix(&$target, $source, $keep = false) {
if (!$source) {
return;
}
$keys = array();
$source = preg_replace_callback(
'/
# Match at start of string or &
(?:^|(?<=&))
# Exclude cases where the period is in brackets, e.g. foo[bar.blarg]
[^=&\[]*
# Affected cases: periods and spaces
(?:\.|%20)
# Keep matching until assignment, next variable, end of string or
# start of an array
[^=&\[]*
/x',
function ($key) use (&$keys) {
$keys[] = $key = base64_encode(urldecode($key[0]));
return urlencode($key);
},
$source
);
if (!$keep) {
$target = array();
}
parse_str($source, $data);
foreach ($data as $key => $val) {
// Only unprocess encoded keys
if (!in_array($key, $keys)) {
$target[$key] = $val;
continue;
}
$key = base64_decode($key);
$target[$key] = $val;
if ($keep) {
// Keep a copy in the underscore key version
$key = preg_replace('/(\.| )/', '_', $key);
$target[$key] = $val;
}
}
}
Run Code Online (Sandbox Code Playgroud)