PHP에서 POST 본문을 얻는 방법?


273

다음을 PHP 페이지에 POST로 제출합니다.

{a:1}

요청 본문입니다 (POST 요청).
PHP에서 그 값을 추출하려면 어떻게해야합니까?

var_dump($_POST); 

작동하지 않는 해결책이 아닙니다.


23
RESTful API를 작성하려는 사람들에게 유용한 질문입니다. 대부분은 스크립트에 제출 된 원시 입력 데이터에 액세스하는 방법을 모릅니다 $_POST. 수퍼 글로벌을 통해 사용할 수 없기 때문 입니다. PHP에는 대응하는 슈퍼 글로벌이 없기 때문에 PUT 요청의 경우 특히 그렇습니다.
rdlowrey


1
POST 요청의 모든 유형의 데이터가 존재하지 않고 컨텐츠 유형이 application / x-www-form-urlencoded 또는 multipart / form-data 인 경우에만 $ _POST 라는 이름 이 잘못 되었다는 점에 주목할 가치 가 있습니다.
Petruza

답변:


549

POST 또는 PUT 요청의 엔티티 본문 (또는 다른 HTTP 메소드)에 액세스하려면 다음을 수행하십시오.

$entityBody = file_get_contents('php://input');

또한 STDIN상수는 이미 열린 스트림 php://input이므로 다음과 같이 할 수도 있습니다.

$entityBody = stream_get_contents(STDIN);

I / O 스트림 문서PHP 수동 항목에서 :

php : // input 은 요청 본문에서 원시 데이터를 읽을 수있는 읽기 전용 스트림입니다. POST 요청의 경우, 사용하는 것이 바람직하다 PHP : // 입력 하는 대신 $HTTP_RAW_POST_DATA이 특별한 php.ini의 지시에 의존하지 않는. 또한 $HTTP_RAW_POST_DATA기본적으로 채워지지 않은 경우 always_populate_raw_post_data를 활성화하는 것보다 메모리를 덜 사용하는 대안입니다. enctype = "multipart / form-data"에는 php : // input을 사용할 수 없습니다.

특히 당신은주의하는 것이 좋습니다 php://input스트림에 관계없이 당신이 웹 SAPI에 액세스하는 방법, 시크하지 않습니다 . 이는 한 번만 읽을 수 있음을 의미합니다. 대규모 HTTP 엔터티 본문이 정기적으로 업로드되는 환경에서 작업하는 경우 위의 첫 번째 예와 같이 버퍼링하지 않고 스트림 형식으로 입력을 유지하고자 할 수 있습니다.

이와 같은 스트림 리소스를 유지하는 것이 도움이 될 수 있습니다.

<?php

function detectRequestBody() {
    $rawInput = fopen('php://input', 'r');
    $tempStream = fopen('php://temp', 'r+');
    stream_copy_to_stream($rawInput, $tempStream);
    rewind($tempStream);

    return $tempStream;
}

php://temp특정 양의 데이터가 저장된 후 파일 시스템 스토리지로 투명하게 전환되므로 메모리 소비를 관리 할 수 ​​있습니다 (기본적으로 2M). 이 크기는 php.ini 파일 또는 추가하여 조작 할 수있는 /maxmemory:NN곳, NN바이트, 임시 파일을 사용하기 전에 메모리에 유지하는 데이터의 최대 금액입니다.

물론, 입력 스트림을 검색해야 할 충분한 이유가 없다면 웹 응용 프로그램에서이 기능이 필요하지 않습니다. HTTP 요청 엔터티 본문을 한 번 읽는 것으로 충분합니다. 앱이 수행 할 작업을 파악하는 동안 클라이언트를 하루 종일 기다리지 마십시오.

php : // input은 Content-Type: multipart/form-data헤더를 지정하는 요청 ( enctype="multipart/form-data"HTML 형식)에 사용할 수 없습니다 . 이것은 PHP가 이미 폼 데이터를 $_POST슈퍼 글로벌 로 파싱 한 결과입니다 .


17
그 afaics 유의 하시길 바랍니다 STDIN 스트림은, 예를 통해 mod_fcgid 또는 mod_fastcgi는 등 PHP 사용하여 CGI를 실행하는 시스템에서 사용할 수 없습니다
SCY

그러나 요청과 함께 변수 (양식 데이터로)를 전달하고 있습니다. 어떻게 지정된 값에 액세스 할 수 있습니까, grant_type = password & username = user & password = pass를 요청과 함께 양식 데이터 본문으로 전달하고 있습니다. entityBody "
Anvar Pk

내 테스트에 따르면, 이것은 내용 유형에 대해서도 php://input비어 application/x-www-form-urlencoded있습니다 (이외에도 multipart/form-data)
YakovL

6
@scy의 응답을 확장하려면 STDIN을 사용할 수 없지만 사용할 수는 없습니다 php://input. 따라서 (빠른) CGI 구성 stream_get_contents(STDIN)은 작동하지 않습니다 file_get_contents("php://input").
Sinus Mackowaty

16

배열의 반환 값

 $data = json_decode(file_get_contents('php://input'), true);

이 시나리오에서는 이제 $data연관 배열을 반복하여 각 값이 원하는 방식으로 인코딩되는지 확인해야합니다. 사물을 보는 "stream-to-datatype"방식은 간단 할 수 있지만, 스트림 필터를 사용하여 "스트림 형식"으로 인코딩하는 것만 큼 효율적이지 않을 수 있습니다. 인코딩 문제를 처리하지 않고 단순히 소독 및 유효성 검사를 수행하는 경우 단계가 누락 된 것입니다.
Anthony Rutledge

13

비어있는 이유 $_POST는 요청이 아니 POST거나 POST더 이상 아니기 때문입니다 ... 요청으로 시작되었지만 어딘가에 리디렉션 301되었거나 302이로 전환되었습니다 GET!

검사 $_SERVER['REQUEST_METHOD']이러한 경우 확인.

이것이 발생하지 않아야하지만 여전히 발생하는 이유에 대한 자세한 내용은 https://stackoverflow.com/a/19422232/109787 을 참조 하십시오 .


1
이 질문은 REST API 플랫폼 개발과 관련하여 요청되었습니다.
Itay Moav -Malimovka

무슨 말인지 모르겠어요? REST API는 경로에서 리디렉션을 찾을 수있을뿐만 아니라 내가 가진 문제입니다.
Legolas

나는 질문을 할 때 버그를 해결하려는 것이 아니라 개발 방법을 찾으려고 노력했다.
Itay Moav-말리 모프 카

3
이 힌트는 내 하루를 구했다. 수신 서버는 https whoch로 리디렉션하도록 일부 API 클라이언트를 중단하도록 재구성되었습니다.
DesertEagle

실제로 내 요청은 POST였지만 검사 후에는임을 보여주었습니다 GET. /URL 끝에을 추가하면 POST가 표시되기 시작했습니다. 기묘한!
zackygaurav

4

7
원시 POST 데이터에 액세스하기 위해 선호되는 방법은 php://input입니다. $HTTP_RAW_POST_DATA에서 사용할 수 없습니다 enctype="multipart/form-data".
nullability

38
이 기능은 PHP 5.6.0에서 더 이상 사용되지 않으며 PHP 7.0.0부터 제거되었습니다.
Charles


2

당신이있는 경우 PECL을 / HTTP 확장 설치, 당신은이를 사용할 수 있습니다 :

$request = new http\Env\Request();
$request->getBody();

2
function getPost()
{
    if(!empty($_POST))
    {
        // when using application/x-www-form-urlencoded or multipart/form-data as the HTTP Content-Type in the request
        // NOTE: if this is the case and $_POST is empty, check the variables_order in php.ini! - it must contain the letter P
        return $_POST;
    }

    // when using application/json as the HTTP Content-Type in the request 
    $post = json_decode(file_get_contents('php://input'), true);
    if(json_last_error() == JSON_ERROR_NONE)
    {
        return $post;
    }

    return [];
}

print_r(getPost());

이 논리 비트가 누락 된 것은 Content-Type 헤더에있는 값을 테스트하는 것입니다. JSON을 제출 했어야하는 $ _POST가 비어 있거나 json_last_error() == JSON_ERROR_NONEis false인 경우 빈 배열을 반환해야한다는 것은 아닙니다 . 누군가 XML 또는 YAML을 제출하면 어떻게 되나요? Content-Type에 대한 테스트를 추가하고 거기서 시작하십시오.
Anthony Rutledge

또한 HTTP 요청 방법은 입력 데이터를 허용할지 여부를 결정하는 요소가 될 수 있습니다. $_SERVER유용한 값을 확인 하려면 superglobal을 참조 하십시오.
Anthony Rutledge

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.