답변:
그 이유는 php://input
컨텐츠 유형에 관계없이 요청의 HTTP 헤더 다음에 모든 원시 데이터 를 리턴하기 때문입니다 .
PHP superglobal 은 다음 중 하나 인 데이터 $_POST
만 랩핑 해야 합니다.
application/x-www-form-urlencoded
(간단한 양식 게시물의 표준 콘텐츠 유형) 또는multipart/form-data
(주로 파일 업로드에 사용됨)이는 사용자 에이전트가 지원 해야하는 유일한 컨텐츠 유형이기 때문 입니다. 따라서 서버와 PHP는 전통적으로 다른 콘텐츠 유형을 기대하지 않습니다 (그렇지 않다는 의미는 아님).
따라서 좋은 오래된 HTML을 POST form
하면 요청은 다음과 같습니다.
POST /page.php HTTP/1.1
key1=value1&key2=value2&key3=value3
그러나 Ajax를 많이 사용하는 경우이 probaby에는 유형 (문자열, 정수, 부울) 및 구조 (배열, 객체) 로보 다 복잡한 데이터를 교환하는 것이 포함되므로 대부분의 경우 JSON이 최선의 선택입니다. 그러나 JSON 페이로드가있는 요청은 다음과 같습니다.
POST /page.php HTTP/1.1
{"key1":"value1","key2":"value2","key3":"value3"}
내용은 이제 application/json
(또는 위에서 언급 한 것 중 적어도 하나는 아니므로) PHP의 $_POST
-wrapper는 (아직) 처리 방법을 모릅니다.
데이터는 여전히 존재하므로 래퍼를 통해 액세스 할 수 없습니다. 당신은 원시 형식으로 직접 가져올 필요가 그래서 file_get_contents('php://input')
( 이 아니에요 한로 multipart/form-data
인코딩 된 ).
XML 데이터 또는 기타 비표준 컨텐츠 유형에 액세스하는 방법도 있습니다.
application/json
유효한 데이터 소스로 인식하는 것을 막는 것은 없습니다 $_POST
. 또한 해당 지원에 대한 게시 된 요청도 있습니다.
php://input
데이터의 원시 바이트를 제공 할 수 있습니다. POST 된 데이터가 JSON으로 인코딩 된 구조 인 경우에 유용하며, 이는 종종 AJAX POST 요청의 경우입니다.
이를 수행하는 기능은 다음과 같습니다.
/**
* Returns the JSON encoded POST data, if any, as an object.
*
* @return Object|null
*/
private function retrieveJsonPostData()
{
// get the raw POST data
$rawData = file_get_contents("php://input");
// this returns null if not valid json
return json_decode($rawData);
}
이 $_POST
배열은 기존 POST에서 제출 한 양식의 키-값 데이터를 처리 할 때 더 유용합니다. POST 된 데이터가 인식 가능한 형식 인 경우에만 작동합니다 application/x-www-form-urlencoded
( 일반적으로 http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4 참조).
true
두 번째 매개 변수로 전달 json_decode
하면 연관 배열이 반환됩니다.
PHP는 HTTP 요청을 처리하기위한 인터페이스와 같은 순수한 REST (GET, POST, PUT, PATCH, DELETE)를 명시 적으로 제공하도록 설계되지 않았습니다 .
그러나 $_POST
, $_GET
및 $_FILES
자동 전역 , 그리고 기능은 filter_input_array()
보통 사람의 / 평신도의 요구에 매우 유용합니다.
$_POST
(및 $_GET
)의 가장 큰 장점은 입력 데이터가 PHP에 의해 자동으로 URL 디코딩 된다는 것 입니다. 표준 GET 요청 내의 쿼리 문자열 매개 변수에 대해서는 그렇게 할 필요조차 없습니다.
프로그래밍 지식이 발전하고 JavaScript XmlHttpRequest
객체 (일부는 jQuery) 를 사용하려는 경우이 체계의 한계를 알게됩니다.
$_POST
HTTP Content-Type
헤더 에서 두 가지 미디어 유형을 사용하도록 제한합니다 .
application/x-www-form-urlencoded
,multipart/form-data
서버에 PHP로 데이터 값을 전송하고,이에 표시해야 할 경우에 따라서 $_POST
자동 전역 , 당신은해야한다 를 urlencode 키 / 값 쌍으로 데이터를 클라이언트 측에 및 전송했다 - 초보자를위한 불편한 단계를 (특히 URL의 다른 부분에 다른 형식의 urlencoding (일반, 원시 등)이 필요한지 알아낼 때).
모든 jQuery 사용자에게이 $.ajax()
방법은 JSON을 URL 인코딩 된 키 / 값 쌍으로 변환 한 후 서버로 전송합니다. 을 설정하여이 동작을 무시할 수 있습니다 processData: false
. $ .ajax () documentation을 읽고 Content-Type 헤더에 올바른 미디어 유형을 보내는 것을 잊지 마십시오.
일반적으로 HTML 양식을 사용하여 일반적인 동기식 (전체 페이지를 다시 그릴 때) HTTP 요청을 수행하는 경우 사용자 에이전트 (웹 브라우저)가 양식 데이터를 표시합니다. XmlHttpRequest
객체를 사용하여 비동기 HTTP 요청을 수행하려면 해당 데이터를 $_POST
superglobal 에 표시하려면 urlencoded 문자열을 작성하여 보내야합니다 .
JavaScript 배열 또는 객체를 urlencoded 문자열로 변환하면 많은 개발자가 방해를 받습니다 ( Form Data 와 같은 새로운 API를 사용하더라도 ). 오히려 JSON을 보낼 수있을뿐 아니라 클라이언트 코드에서 보다 효율적 으로 처리 할 수 있습니다.
평균 웹 개발자는 XmlHttpRequest
객체, 전역 함수, 문자열 함수, 배열 함수 및 정규 표현식과 같은 사용자 를 사용하는 법을 배우지 않습니다 . 그들을위한 Urlencoding은 악몽입니다. ;-)
직관적 인 XML과 JSON 처리가 부족한 PHP는 많은 사람들을 혼란시킵니다. 지금까지는 PHP의 일부라고 생각할 것입니다.
XML, JSON 및 YAML에는 모두 HTTP Content-Type
헤더에 넣을 수있는 미디어 유형이 있습니다 .
얼마나 많은 봐 미디어 유형 (구, MIME 유형이) IANA에 의해 정의된다.
얼마나 많은 HTTP 헤더 가 있는지보십시오 .
은 Using php://input
스트림하면 PHP가 세계에 강요했다고 추상화 아기 돌보기 / 손을 잡고 레벨을 우회 할 수 있습니다. :-) 큰 힘에는 큰 책임이 따른다!
이제를 통해 스트리밍되는 데이터 값을 처리하기 전에 php://input
몇 가지 작업을 수행해야합니다.
아하! 예, 응용 프로그램으로 전송되는 데이터 스트림이 UTF-8로 인코딩되기를 원할 수 있지만 이것이 있는지 여부를 어떻게 알 수 있습니까?
php://input
.먼저 얼마가 있는지 모르면서 스트림 데이터를 처리하려고합니까? 그건 끔찍한 생각 입니다. Content-Length
스푸핑 될 수 있으므로 스트리밍 된 입력 크기에 대한 지침으로 HTTP 헤더 에만 의존 할 수 없습니다 .
당신은 필요합니다 :
스트림의 현재 인코딩을 모르고 스트림 데이터를 UTF-8로 변환하려고합니까? 어떻게? iconv 스트림 필터 ( iconv 스트림 필터 예 )는 이와 같이 시작 및 종료 인코딩을 원하는 것 같습니다.
'convert.iconv.ISO-8859-1/UTF-8'
따라서 양심적이라면 다음이 필요합니다.
( 업데이트 : 'convert.iconv.UTF-8/UTF-8'
모든 것을 UTF-8로 강제하지만, iconv 라이브러리가 번역 방법을 알지 못하는 문자를 고려해야합니다. 즉, 문자를 번역 할 수 없을 때 수행 할 조치를 정의해야합니다. : 1) 더미 문자를 삽입합니다. 2) 실패 / 던지기 및 예외).
Content-Encoding
다음과 같이 압축과 같은 것을 나타낼 수 있으므로 HTTP 헤더 에만 의존 할 수는 없습니다 . iconv와 관련하여 결정을 내리려는 것은 아닙니다.
Content-Encoding: gzip
1 부 : HTTP 요청 관련
2 부 : 스트림 데이터 관련
III 부 : 데이터 유형 관련
데이터는 여전히 URL 인코딩 된 문자열 일 수 있으며 구문 분석하고 URL 디코딩해야합니다.
IV 부 : 데이터 가치 관련
입력 데이터를 필터링하십시오.
입력 데이터를 확인하십시오.
$_POST
입력에 대한 제한을위한 php.ini의 설정에 따라 자동 전역은 평신도를위한 간단합니다. 그러나 문자 인코딩을 처리하는 것은 스트림을 사용할 때 훨씬 직관적이고 효율적이며, 적절한 인코딩을 위해 입력 값을 확인하기 위해 슈퍼 글로벌 (또는 일반적으로 배열)을 반복 할 필요가 없기 때문입니다.
그래서 php : // input stream 에서 POST 데이터를 가져 오는 함수를 작성했습니다 .
따라서 여기서의 과제는 PUT, DELETE 또는 PATCH 요청 방법으로 전환하고 해당 요청과 함께 전송 된 포스트 데이터를 얻는 것입니다.
나는 비슷한 도전을 가진 사람을 위해 이것을 공유하고 있습니다. 아래 기능은 내가 생각해 낸 것입니다. 도움이 되길 바랍니다!
/**
* @method Post getPostData
* @return array
*
* Convert Content-Disposition to a post data
*/
function getPostData() : array
{
// @var string $input
$input = file_get_contents('php://input');
// continue if $_POST is empty
if (strlen($input) > 0 && count($_POST) == 0 || count($_POST) > 0) :
$postsize = "---".sha1(strlen($input))."---";
preg_match_all('/([-]{2,})([^\s]+)[\n|\s]{0,}/', $input, $match);
// update input
if (count($match) > 0) $input = preg_replace('/([-]{2,})([^\s]+)[\n|\s]{0,}/', '', $input);
// extract the content-disposition
preg_match_all("/(Content-Disposition: form-data; name=)+(.*)/m", $input, $matches);
// let's get the keys
if (count($matches) > 0 && count($matches[0]) > 0)
{
$keys = $matches[2];
foreach ($keys as $index => $key) :
$key = trim($key);
$key = preg_replace('/^["]/','',$key);
$key = preg_replace('/["]$/','',$key);
$key = preg_replace('/[\s]/','',$key);
$keys[$index] = $key;
endforeach;
$input = preg_replace("/(Content-Disposition: form-data; name=)+(.*)/m", $postsize, $input);
$input = preg_replace("/(Content-Length: )+([^\n]+)/im", '', $input);
// now let's get key value
$inputArr = explode($postsize, $input);
// @var array $values
$values = [];
foreach ($inputArr as $index => $val) :
$val = preg_replace('/[\n]/','',$val);
if (preg_match('/[\S]/', $val)) $values[$index] = trim($val);
endforeach;
// now combine the key to the values
$post = [];
// @var array $value
$value = [];
// update value
foreach ($values as $i => $val) $value[] = $val;
// push to post
foreach ($keys as $x => $key) $post[$key] = isset($value[$x]) ? $value[$x] : '';
if (is_array($post)) :
$newPost = [];
foreach ($post as $key => $val) :
if (preg_match('/[\[]/', $key)) :
$k = substr($key, 0, strpos($key, '['));
$child = substr($key, strpos($key, '['));
$child = preg_replace('/[\[|\]]/','', $child);
$newPost[$k][$child] = $val;
else:
$newPost[$key] = $val;
endif;
endforeach;
$_POST = count($newPost) > 0 ? $newPost : $post;
endif;
}
endif;
// return post array
return $_POST;
}
사용 방법의 간단한 예
<?php
if(!isset($_POST) || empty($_POST)) {
?>
<form name="form1" method="post" action="">
<input type="text" name="textfield"><br />
<input type="submit" name="Submit" value="submit">
</form>
<?php
} else {
$example = file_get_contents("php://input");
echo $example; }
?>