PHP가 $_GET 또는 $_POST 배열에서 '.' 문자의 치환을 중지하도록 합니다.
를 PHP와 함께 .
$ PHP를 통한 으로 $_GET 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>";
...는 다음을 출력합니다.
url is /SpShipTool/php/testGetUrl.php?x.y=a.b
x.y is .
x_y is a.b.
...내 질문은 이것이다: 내가 이 일을 멈출 수 있는 방법은 없을까?내가 뭘 했기에 이런 일을 당했는지 아무리 생각해도 모르겠어
현재 사용하고 있는 PHP 버전은 5.2.4-2ubuntu5.3입니다.
그 이유에 대한 PHP.net의 설명은 다음과 같습니다.
들어오는 변수 이름의 점
일반적으로 PHP는 스크립트로 전달될 때 변수 이름을 변경하지 않습니다.단, 점( 마침표, 마침표)은 PHP 변수 이름의 유효한 문자가 아닙니다.그 이유는 다음과 같습니다.
<?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를 사용합니다).
오랫동안 질문에 답했지만 실제로는 더 나은 답변(또는 회피책)이 있습니다.PHP를 사용하면 원시 입력 스트림에서 다음과 같은 작업을 수행할 수 있습니다.
$query_string = file_get_contents('php://input');
그러면 $_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'); }
?>
오픈에 큰 도움이 되다ID 매개 변수. 각각 '.'와 '_'를 모두 포함하며, 각각 특정 의미를 가집니다.
위의 코멘트에서 Johan에 의한 실제 답변을 강조 표시 - 저는 방금 투고 전체를 문제를 완전히 우회하는 톱 레벨 어레이로 정리했습니다.부하 처리는 필요 없습니다.
당신이 하는 형태로
<input name="data[database.username]">
<input name="data[database.password]">
<input name="data[something.else.really.deep]">
대신
<input name="database.username">
<input name="database.password">
<input name="something.else.really.deep">
포스트 핸들러에서 개봉하기만 하면 됩니다.
$posdata = $_POST['data'];
나의 견해는 완전히 틀에 박힌 것이었기 때문에, 나에게 이것은 두 줄의 변화였다.
참고로, 필드 이름에 점을 사용하여 그룹화된 데이터의 트리를 편집합니다.
표준규격에 준거하여 딥 어레이와 연동되는 솔루션을 원하십니까(예:?param[2][5]=10
? ) 。
이 문제의 가능한 모든 원인을 수정하려면 PHP 코드 맨 위에 신청하십시오.
$_GET = fix( $_SERVER['QUERY_STRING'] );
$_POST = fix( file_get_contents('php://input') );
$_COOKIE = fix( $_SERVER['HTTP_COOKIE'] );
이 기능은 2013년 여름휴가 때 생각해 낸 멋진 아이디어입니다.이름을 한 후 regex를 합니다. 모든 쿼리 이름을 가져와 인코딩한 다음(그래서 점이 보존됨) 일반을 사용합니다.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;
}
이는 마침표가 변수 이름에 유효하지 않은 문자이기 때문에 발생하며, 그 이유는 PHP 구현에 매우 깊이 있기 때문에 쉬운 수정은 아직 없습니다.
그 사이에, 다음의 방법으로 이 문제를 해결할 수 있습니다.
- 에 대한 은 adda를 .
php://input
또는 POST의$_SERVER['QUERY_STRING']
GET 데 for for - 변환 함수를 사용합니다.
변환 PHP > .4는 각 , 의 「(PHP >= 5.4)」를 합니다.parse_str()
;가 완료되면 16진수 이름을 원래 형식으로 되돌립니다.
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']);
또는 다음 중 하나를 선택합니다.
// handle posted data (this only works with application/x-www-form-urlencoded)
$data = parse_qs(file_get_contents('php://input'));
이 접근방식은 Rock 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;
}
}
}
이 문제가 발생하는 이유는 PHP의 오래된 register_globals 기능 때문입니다..문자는 변수 이름에 유효한 문자가 아니기 때문에 호환성을 확인하기 위해 밑줄로 덮어씁니다.
즉, URL 변수에 마침표를 찍는 것은 좋은 방법이 아닙니다.
PHP가 $_GET 또는 $_POST 배열에서 문자 그대로 '.'를 대체하는 방법을 찾는다면, 그러한 방법 중 하나는 PHP의 소스를 수정하는 것입니다(이 경우 비교적 간단합니다).
경고: PHP C 소스를 수정하는 것은 고급 옵션입니다!
또한 동일한 수정을 제안하는 이 PHP 버그 보고서를 참조하십시오.
탐색하려면 다음 작업을 수행해야 합니다.
소스 변경 자체는 사소한 것으로, 의 1행의 절반만 갱신할 필요가 있습니다.main/php_variables.c
:
....
/* ensure that we don't have spaces or dots in the variable name (not binary safe) */
for (p = var; *p; p++) {
if (*p == ' ' /*|| *p == '.'*/) {
*p='_';
....
: 오리지널과의 : ★★★★★★★★★★★★★★★★★★★★★★★★★★」|| *p == '.'
가
출력 예:
QUERY_STRING "의 a.a[]=bb&a.a[]=BB&c%20c=dd
, 달리기, 뛰다.<?php print_r($_GET);
츠키다
어레이([a.a] => 어레이([0] => bb[1] => BB) [c_c] => dd)
주의:
- 이 패치는 원래 질문에만 대응합니다(스페이스가 아닌 도트 치환을 중지합니다).
- 이 패치로 실행하는 것은 스크립트 레벨의 솔루션보다 빠릅니다만, PHP 자체를 변경하지 않기 때문에, 이러한 pure.php의 답변은 여전히 일반적으로 바람직합니다.
- 는 여기서 하기 위해 의 변화를 하는 어프로치를 할 수 .
parse_str()
및 (사용할 수 없는 경우) 저속 메서드로 폴백합니다.
이 문제에 대한 나의 해결책은 빠르고 지저분했지만, 나는 여전히 그것을 좋아한다.저는 단지 양식에 체크된 파일명의 목록을 올리고 싶었습니다.하였습니다.base64_encode
후, 「」, 「」로 합니다.base64_decode
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
Rock의 솔루션을 검토한 후 아래 답변의 한계와 crb의 위, 그리고 Rock의 솔루션을 해결하는 버전을 생각해냈습니다.개선된 버전을 참조하십시오.
위의 @crb의 답변은 좋은 시작이지만 몇 가지 문제가 있습니다.
- 이름에 ""가 있는 필드만 재처리하면 됩니다. 이러한 필드만 재처리하면 됩니다.
- 네이티브 PHP 처리와 같은 방법으로 어레이를 처리하지 못합니다(예: "foo.bar[]").
다음 솔루션은 이 두 가지 문제를 모두 해결했습니다(처음 게시된 이후 업데이트되었습니다).이는 테스트에서 위의 답변보다 약 50% 빠르지만 데이터가 동일한 키를 갖는 경우(또는 동일한 키를 추출하는 경우(foo.bar 및 foo_bar 둘 다 foo_bar로 추출됨)에는 대응하지 않습니다.
<?php
public function fix2(&$target, $source, $keep = false) {
if (!$source) {
return;
}
preg_match_all(
'/
# 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',
$source,
$matches
);
foreach (current($matches) as $key) {
$key = urldecode($key);
$badKey = preg_replace('/(\.| )/', '_', $key);
if (isset($target[$badKey])) {
// Duplicate values may have already unset this
$target[$key] = $target[$badKey];
if (!$keep) {
unset($target[$badKey]);
}
}
}
}
아래에 포함된 함수 "getRealPostArray()"는 그다지 좋은 솔루션은 아니지만 어레이를 처리하고 "alpha_beta"와 "alpha.beta" 두 가지 이름을 모두 지원합니다.
<input type='text' value='First-.' name='alpha.beta[a.b][]' /><br>
<input type='text' value='Second-.' name='alpha.beta[a.b][]' /><br>
<input type='text' value='First-_' name='alpha_beta[a.b][]' /><br>
<input type='text' value='Second-_' name='alpha_beta[a.b][]' /><br>
var_dump($_POST)는 다음을 생성합니다.
'alpha_beta' =>
array (size=1)
'a.b' =>
array (size=4)
0 => string 'First-.' (length=7)
1 => string 'Second-.' (length=8)
2 => string 'First-_' (length=7)
3 => string 'Second-_' (length=8)
var_dump(getRealPostArray())는 다음을 생성합니다.
'alpha.beta' =>
array (size=1)
'a.b' =>
array (size=2)
0 => string 'First-.' (length=7)
1 => string 'Second-.' (length=8)
'alpha_beta' =>
array (size=1)
'a.b' =>
array (size=2)
0 => string 'First-_' (length=7)
1 => string 'Second-_' (length=8)
기능은 다음과 같습니다.
function getRealPostArray() {
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {#Nothing to do
return null;
}
$neverANamePart = '~#~'; #Any arbitrary string never expected in a 'name'
$postdata = file_get_contents("php://input");
$post = [];
$rebuiltpairs = [];
$postraws = explode('&', $postdata);
foreach ($postraws as $postraw) { #Each is a string like: 'xxxx=yyyy'
$keyvalpair = explode('=',$postraw);
if (empty($keyvalpair[1])) {
$keyvalpair[1] = '';
}
$pos = strpos($keyvalpair[0],'%5B');
if ($pos !== false) {
$str1 = substr($keyvalpair[0], 0, $pos);
$str2 = substr($keyvalpair[0], $pos);
$str1 = str_replace('.',$neverANamePart,$str1);
$keyvalpair[0] = $str1.$str2;
} else {
$keyvalpair[0] = str_replace('.',$neverANamePart,$keyvalpair[0]);
}
$rebuiltpair = implode('=',$keyvalpair);
$rebuiltpairs[]=$rebuiltpair;
}
$rebuiltpostdata = implode('&',$rebuiltpairs);
parse_str($rebuiltpostdata, $post);
$fixedpost = [];
foreach ($post as $key => $val) {
$fixedpost[str_replace($neverANamePart,'.',$key)] = $val;
}
return $fixedpost;
}
crb를 사용하여 저는 이 파일을 재현하고 싶었습니다.$_POST
다만, 클라이언트와 서버 양쪽에서 올바르게 인코딩 및 디코딩하고 있는 것을 확인할 필요가 있습니다.캐릭터가 정말 무효이고 그것이 정말 유효한지를 이해하는 것이 중요합니다.또한 예외 없이 database 명령어와 함께 사용하기 전에 클라이언트 데이터를 항상 이스케이프해야 합니다.
<?php
unset($_POST);
$_POST = array();
$p0 = explode('&',file_get_contents('php://input'));
foreach ($p0 as $key => $value)
{
$p1 = explode('=',$value);
$_POST[$p1[0]] = $p1[1];
//OR...
//$_POST[urldecode($p1[0])] = urldecode($p1[1]);
}
print_r($_POST);
?>
이것은 개별 케이스에만 사용하는 것을 추천합니다.당장 프라이머리 헤더 파일의 맨 위에 배치했을 때의 단점은 잘 모르겠습니다.
현재 솔루션(앞의 토픽 응답에 근거):
function parseQueryString($data)
{
$data = rawurldecode($data);
$pattern = '/(?:^|(?<=&))[^=&\[]*[^=&\[]*/';
$data = preg_replace_callback($pattern, function ($match){
return bin2hex(urldecode($match[0]));
}, $data);
parse_str($data, $values);
return array_combine(array_map('hex2bin', array_keys($values)), $values);
}
$_GET = parseQueryString($_SERVER['QUERY_STRING']);
언급URL : https://stackoverflow.com/questions/68651/get-php-to-stop-replacing-characters-in-get-or-post-arrays
'itsource' 카테고리의 다른 글
콘솔로 이동합니다.writline 및 System.out.println (0) | 2022.09.14 |
---|---|
JavaScript에서 여러 CSS 스타일을 설정하려면 어떻게 해야 합니까? (0) | 2022.09.14 |
EF 코어 저속 벌크 인서트(80k 행까지) (0) | 2022.09.14 |
MySQL 일부 외부 키 제거 (0) | 2022.09.14 |
PHP를 사용하여 IP 주소 국가 가져오기 (0) | 2022.09.13 |