PHP로 POST 요청을 보내려면 어떻게해야합니까?


656

실제로 검색이 끝나면 내용을 읽고 싶습니다. 문제는 URL이 POST메소드 만 허용하며 메소드에 대한 조치를 취하지 않는다는 것입니다 GET.

domdocument또는 의 도움으로 모든 내용을 읽어야합니다 file_get_contents(). 메소드를 사용하여 매개 변수를 보내고 POST내용을 통해 읽을 수있는 방법이 PHP있습니까?

답변:


1260

PHP5를 이용한 CURL-less 방법 :

$url = 'http://server.com/path';
$data = array('key1' => 'value1', 'key2' => 'value2');

// use key 'http' even if you send the request to https://...
$options = array(
    'http' => array(
        'header'  => "Content-type: application/x-www-form-urlencoded\r\n",
        'method'  => 'POST',
        'content' => http_build_query($data)
    )
);
$context  = stream_context_create($options);
$result = file_get_contents($url, false, $context);
if ($result === FALSE) { /* Handle error */ }

var_dump($result);

메소드 및 헤더 추가 방법에 대한 자세한 정보는 PHP 매뉴얼을 참조하십시오.


64
헤더에 배열을 사용하기로 결정한 경우 키 또는 값을 '\ r \ n'으로 끝내지 마십시오. stream_context_create ()는 첫 번째 '\ 연구 \ n'에있는 텍스트 소요됩니다
랩터

11
file_get_contents()fopen 래퍼가 활성화 된 경우에만 URL을 파일 이름 으로 사용할 수 있습니다. php.net/manual/en/…
Pino

3
@I lovefile_get_contents()
deadlock

14
CURL을 사용하지 않는 특별한 이유가 있습니까?
jvannistelrooy

37
@jvannistelrooy PHP 용 CURL은 모든 환경에 존재하지 않는 확장 기능이지만 file_get_contents()PHP의 핵심 부분입니다. 또한 확장을 불필요하게 사용하면 앱의 공격 범위가 넓어 질 수 있습니다. 예 : Google PHP curl cve
Pocketsand

139

cURL을 사용할 수 있습니다 :

<?php
//The url you wish to send the POST request to
$url = $file_name;

//The data you want to send via POST
$fields = [
    '__VIEWSTATE '      => $state,
    '__EVENTVALIDATION' => $valid,
    'btnSubmit'         => 'Submit'
];

//url-ify the data for the POST
$fields_string = http_build_query($fields);

//open connection
$ch = curl_init();

//set the url, number of POST vars, POST data
curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_POST, true);
curl_setopt($ch,CURLOPT_POSTFIELDS, $fields_string);

//So that curl_exec returns the contents of the cURL; rather than echoing it
curl_setopt($ch,CURLOPT_RETURNTRANSFER, true); 

//execute post
$result = curl_exec($ch);
echo $result;
?>

3
이것은 내용이없는 페이지로 보내는 페이지가 file_get_contents 버전이 작동하지 않아서 나를 위해 일했습니다.
CommentLuv

9
file_get_contents 솔루션은 allow_url_fopen이 꺼져있는 PHP 구성 (예 : 공유 호스팅)에서 작동하지 않습니다. 이 버전은 컬 라이브러리를 사용하며 가장 "유니버설"인 것 같아서 투표를하겠습니다
Dayron Gallardo


4
그다지 중요하지는 않지만 CURLOPT_POSTFIELDS 매개 변수 데이터는 실제로 문자열 ( "urlified")로 변환 될 필요가 없습니다. Quote : "이 매개 변수는 'para1 = val1 & para2 = val2 & ...'와 같은 urlencoded 문자열 또는 필드 이름을 키로, 필드 데이터를 값으로하는 배열로 전달 될 수 있습니다. value가 배열 인 경우 Content-Type 헤더가 multipart / form-data로 설정됩니다. " 링크 : php.net/manual/en/function.curl-setopt.php .
Edward

2
또한 다르게 쓰는 것에 대한 위반은 없지만 CURLOPT_POST 매개 변수가 매뉴얼 페이지에서 부울로 설정한다고 말하는 이유를 모르겠습니다. 인용문 : "CURLOPT_POST : 일반 HTTP POST를 수행하려면 참입니다." 링크 : php.net/manual/en/function.curl-setopt.php .
Edward

68

curl을 사용하여 데이터를 게시하려면 다음 함수를 사용하십시오. $ data는 게시 할 필드 배열입니다 (http_build_query를 사용하여 올바르게 인코딩 됨). 데이터는 application / x-www-form-urlencoded를 사용하여 인코딩됩니다.

function httpPost($url, $data)
{
    $curl = curl_init($url);
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($data));
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    $response = curl_exec($curl);
    curl_close($curl);
    return $response;
}

@Edward는 curl이 CURLOPT_POSTFIELDS 매개 변수에 전달 된 배열을 올바르게 인코딩하므로 http_build_query가 생략 될 수 있다고 언급하지만이 경우 데이터는 multipart / form-data를 사용하여 인코딩됩니다.

application / x-www-form-urlencoded를 사용하여 데이터를 인코딩 할 것으로 예상되는 API와 함께이 기능을 사용합니다. 그래서 http_build_query ()를 사용합니다.


CURLOPT_POSTFIELDS에 배열을 전달하면 바람직하지 않은 multipart / form-data를 사용하여 데이터가 인코딩됩니다.
Dima L.

사용자가 file_get_contents를 요청 했으므로 default_stream_context를 변경하기위한 솔루션이 필요합니다
Radon8472

명확히하기 위해 : @DimaL 생각합니다. 삭제 된 주석에 응답하고 있습니다. multipart / form-data 로의 출력을 피하면서 배열을 문자열 http_build_query로 변환 $data합니다.
ToolmakerSteve

@ Radon8472- 내용 ... CURLOPT_RETURNTRANSFER, true$response포함합니다.
ToolmakerSteve

@ToolmakerSteve 내가 말했듯이 질문은 file_get_contents많은 사람들이 가지고 있지 않은 CURL이 필요합니다. 따라서 귀하의 솔루션은 효과가 있지만 기본 내장 파일 / 스트림 기능 으로이 작업을 수행하는 방법에 대한 질문에 대답하지 않습니다.
Radon8472

42

전체 단위 테스트를 거쳤으며 최신 코딩 방법 을 사용하는 오픈 소스 패키지 구슬 을 사용하는 것이 좋습니다 .

Guzzle 설치

프로젝트 폴더의 명령 행으로 이동하여 다음 명령을 입력하십시오 (패키지 관리자 작성기 가 이미 설치되어 있다고 가정 ). Composer 설치 방법에 대한 도움이 필요 하면 여기를 참조하십시오 .

php composer.phar require guzzlehttp/guzzle

Guzzle을 사용하여 POST 요청 보내기

Guzzle은 가벼운 객체 지향 API를 사용하므로 매우 간단합니다.

// Initialize Guzzle client
$client = new GuzzleHttp\Client();

// Create a POST request
$response = $client->request(
    'POST',
    'http://example.org/',
    [
        'form_params' => [
            'key1' => 'value1',
            'key2' => 'value2'
        ]
    ]
);

// Parse the response object, e.g. read the headers, body, etc.
$headers = $response->getHeaders();
$body = $response->getBody();

// Output headers and body for debugging purposes
var_dump($headers, $body);

7
이 기능이 이미 게시 한 기본 PHP 솔루션과 cURL에 비해 어떤 이점이 있는지 아는 것이 유용합니다.
artfulrobot

9
@artfulrobot : 네이티브 PHP 솔루션에는 많은 문제 (예 : https 연결, 인증서 확인 등)가 있으므로 거의 모든 PHP 개발자가 cURL을 사용합니다. 이 경우 cURL을 사용하지 않는 이유는 무엇입니까? 간단하다 : Guzzle은 "저수준 cURL 처리 문제"를 모두 추상화하는 간단하고 쉽고 가벼운 인터페이스를 가지고있다. 어쨌든 현대 PHP를 개발하는 거의 모든 사람들이 Composer를 사용하므로 Guzzle을 사용하는 것은 정말 간단합니다.
Andreas

2
고마워, 나는 guzzle이 인기가 있다는 것을 알고 있지만, 작곡가가 슬픔을 일으키는 유스 케이스 (예 : 이미 다른 버전의 guzzle 또는 기타 종속성을 사용하는 더 큰 소프트웨어 프로젝트를위한 플러그인 개발)가 있으므로이 정보를 아는 것이 좋습니다 솔루션은 가장 강력한 될 것이다 대해 결정
artfulrobot

26

그렇게하면 다른 CURL 메소드가 있습니다.

PHP curl 확장 프로그램이 작동하는 방식을 이해하고 setopt () 호출과 다양한 플래그를 결합하면 간단합니다. 이 예제에는 $ xml 변수가 있는데,이 XML은 보낼 준비가 된 XML을 보유하고 있습니다. 그 내용을 예제의 테스트 방법에 게시하겠습니다.

$url = 'http://api.example.com/services/xmlrpc/';
$ch = curl_init($url);

curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
curl_close($ch);
//process $response

먼저 연결을 초기화 한 다음 setopt ()를 사용하여 몇 가지 옵션을 설정했습니다. 이것들은 PHP에게 사후 요청을하고 있으며, 데이터를 제공하면서 데이터를 전송하고 있다고 알려줍니다. CURLOPT_RETURNTRANSFER 플래그는 curl에게 출력하지 않고 curl_exec의 반환 값으로 출력을 제공하도록 curl에 지시합니다. 그런 다음 전화를 걸고 연결을 닫습니다. 결과는 $ response입니다.


1
세 번째 curl_setopt () 호출에서 첫 번째 인수는 정확 $ch하지 않아야 $curl합니까?
jcomeau_ictx 4

동일한 코드를 사용하여 JSON 데이터를 POST 할 수 있습니까? 그러나 $ xml을 $ json으로 바꾸십시오 (여기서 $ json은 아마도 JSON 문자열입니까?)
Neal Davis

24

우연히 Wordpress를 사용하여 앱을 개발하는 경우 (실제로는 인증, 정보 페이지 등을 간단하게 얻을 수있는 편리한 방법 임) 다음 스 니펫을 사용할 수 있습니다.

$response = wp_remote_post( $url, array('body' => $parameters));

if ( is_wp_error( $response ) ) {
    // $response->get_error_message()
} else {
    // $response['body']
}

웹 서버에서 사용 가능한 항목에 따라 실제 HTTP 요청을 작성하는 여러 가지 방법을 사용합니다. 자세한 내용은 HTTP API 설명서를 참조하십시오 .

Wordpress 엔진을 시작하기 위해 사용자 정의 테마 또는 플러그인을 개발하지 않으려면 wordpress 루트의 격리 된 PHP 파일에서 다음을 수행하면됩니다.

require_once( dirname(__FILE__) . '/wp-load.php' );

// ... your code

테마를 표시하거나 HTML을 출력하지 않으며 Wordpress API로 해킹하십시오!


22

Fred Tanrikut의 컬 기반 답변에 대해 몇 가지 생각을 추가하고 싶습니다. 나는 그들 중 대부분이 이미 위의 답변으로 작성되어 있음을 알고 있지만 모든 답변을 포함하는 답변을 보여주는 것이 좋습니다.

다음은 응답 본문에 관한 curl을 기반으로 HTTP-GET / POST / PUT / DELETE 요청을 작성하기 위해 작성한 클래스입니다.

class HTTPRequester {
    /**
     * @description Make HTTP-GET call
     * @param       $url
     * @param       array $params
     * @return      HTTP-Response body or an empty string if the request fails or is empty
     */
    public static function HTTPGet($url, array $params) {
        $query = http_build_query($params); 
        $ch    = curl_init($url.'?'.$query);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HEADER, false);
        $response = curl_exec($ch);
        curl_close($ch);
        return $response;
    }
    /**
     * @description Make HTTP-POST call
     * @param       $url
     * @param       array $params
     * @return      HTTP-Response body or an empty string if the request fails or is empty
     */
    public static function HTTPPost($url, array $params) {
        $query = http_build_query($params);
        $ch    = curl_init();
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HEADER, false);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $query);
        $response = curl_exec($ch);
        curl_close($ch);
        return $response;
    }
    /**
     * @description Make HTTP-PUT call
     * @param       $url
     * @param       array $params
     * @return      HTTP-Response body or an empty string if the request fails or is empty
     */
    public static function HTTPPut($url, array $params) {
        $query = \http_build_query($params);
        $ch    = \curl_init();
        \curl_setopt($ch, \CURLOPT_RETURNTRANSFER, true);
        \curl_setopt($ch, \CURLOPT_HEADER, false);
        \curl_setopt($ch, \CURLOPT_URL, $url);
        \curl_setopt($ch, \CURLOPT_CUSTOMREQUEST, 'PUT');
        \curl_setopt($ch, \CURLOPT_POSTFIELDS, $query);
        $response = \curl_exec($ch);
        \curl_close($ch);
        return $response;
    }
    /**
     * @category Make HTTP-DELETE call
     * @param    $url
     * @param    array $params
     * @return   HTTP-Response body or an empty string if the request fails or is empty
     */
    public static function HTTPDelete($url, array $params) {
        $query = \http_build_query($params);
        $ch    = \curl_init();
        \curl_setopt($ch, \CURLOPT_RETURNTRANSFER, true);
        \curl_setopt($ch, \CURLOPT_HEADER, false);
        \curl_setopt($ch, \CURLOPT_URL, $url);
        \curl_setopt($ch, \CURLOPT_CUSTOMREQUEST, 'DELETE');
        \curl_setopt($ch, \CURLOPT_POSTFIELDS, $query);
        $response = \curl_exec($ch);
        \curl_close($ch);
        return $response;
    }
}

개량

  • http_build_query를 사용하여 request-array에서 query-string을 가져옵니다 (배열 자체를 사용할 수도 있으므로 http://php.net/manual/en/function.curl-setopt.php 참조 ).
  • 반향 대신 응답을 반환합니다. 그러나 curl_setopt ($ ch, CURLOPT_RETURNTRANSFER, true); 줄을 제거하여 반환을 피할 수 있습니다 . . 그 후 리턴 값은 부울 (true = 요청이 성공하면 오류가 발생 함)이며 응답이 에코됩니다. 참조 : http://php.net/en/manual/function.curl-exec.php
  • curl_close 를 사용하여 curl 처리기의 세션 종료 및 삭제를 정리하십시오 . 참조 : http://php.net/manual/en/function.curl-close.php
  • curl_setopt 함수에 부울 값을 사용하는 대신 임의의 숫자를 사용하십시오. (제로가 아닌 숫자도 true로 간주되지만 true를 사용하면 더 읽기 쉬운 코드가 생성되지만 이는 제 의견입니다)
  • HTTP-PUT / DELETE 호출 기능 (RESTful 서비스 테스트에 유용)

사용 예

가져 오기

$response = HTTPRequester::HTTPGet("http://localhost/service/foobar.php", array("getParam" => "foobar"));

게시하다

$response = HTTPRequester::HTTPPost("http://localhost/service/foobar.php", array("postParam" => "foobar"));

놓다

$response = HTTPRequester::HTTPPut("http://localhost/service/foobar.php", array("putParam" => "foobar"));

지우다

$response = HTTPRequester::HTTPDelete("http://localhost/service/foobar.php", array("deleteParam" => "foobar"));

테스팅

이 간단한 클래스를 사용하여 멋진 서비스 테스트를 수행 할 수도 있습니다.

class HTTPRequesterCase extends TestCase {
    /**
     * @description test static method HTTPGet
     */
    public function testHTTPGet() {
        $requestArr = array("getLicenses" => 1);
        $url        = "http://localhost/project/req/licenseService.php";
        $this->assertEquals(HTTPRequester::HTTPGet($url, $requestArr), '[{"error":false,"val":["NONE","AGPL","GPLv3"]}]');
    }
    /**
     * @description test static method HTTPPost
     */
    public function testHTTPPost() {
        $requestArr = array("addPerson" => array("foo", "bar"));
        $url        = "http://localhost/project/req/personService.php";
        $this->assertEquals(HTTPRequester::HTTPPost($url, $requestArr), '[{"error":false}]');
    }
    /**
     * @description test static method HTTPPut
     */
    public function testHTTPPut() {
        $requestArr = array("updatePerson" => array("foo", "bar"));
        $url        = "http://localhost/project/req/personService.php";
        $this->assertEquals(HTTPRequester::HTTPPut($url, $requestArr), '[{"error":false}]');
    }
    /**
     * @description test static method HTTPDelete
     */
    public function testHTTPDelete() {
        $requestArr = array("deletePerson" => array("foo", "bar"));
        $url        = "http://localhost/project/req/personService.php";
        $this->assertEquals(HTTPRequester::HTTPDelete($url, $requestArr), '[{"error":false}]');
    }
}

나를 위해, "발견되지 않은 오류 : 정의되지 않은 메소드 HTTPRequester :: HTTPost ()에 대한 호출"이라고 표시되어 있습니다. 클래스를 내 .php 파일에 붙여 넣었습니다. 내가해야 할 다른 일이 있습니까?
LinusGeffarth

1
코드를 게시 해 주시겠습니까? 코드 스 니펫이 없으면 무엇이 잘못되었는지 추측하기가 어렵습니다.
mwatzer

내가 말했듯이, 나는 문자 그대로 내 일반 PHP 파일로 복사 했으며이 오류가 발생했습니다.
LinusGeffarth 1

1
이제 문제가 보입니다 .. 예에서 잘못되었습니다! HTTPRequester :: HTTPost () 대신 HTTPRequester :: HTTPPost ()를 호출해야합니다.
mwatzer

1
아 놓치기 쉽다. 여분의 P를 발견하기 전에 5x와 같은 주석을 읽어야했습니다 . 감사!
LinusGeffarth

19

curl-less 방법 의 또 다른 대안은 기본 스트림 함수 를 사용하는 것입니다.

  • stream_context_create():

    옵션 사전 설정에 제공된 옵션으로 스트림 컨텍스트를 작성하고 리턴합니다 .

  • stream_get_contents():

    이미 열린 스트림 리소스 에서 작동하고 최대 maxbyte 바이트 까지 지정된 오프셋 에서 시작 하여 문자열의 나머지 내용을 반환 file_get_contents()한다는 점을 제외하고 stream_get_contents() 동일합니다 .

이것들을 가진 POST 함수는 단순히 다음과 같을 수 있습니다 :

<?php

function post_request($url, array $params) {
  $query_content = http_build_query($params);
  $fp = fopen($url, 'r', FALSE, // do not use_include_path
    stream_context_create([
    'http' => [
      'header'  => [ // header array does not need '\r\n'
        'Content-type: application/x-www-form-urlencoded',
        'Content-Length: ' . strlen($query_content)
      ],
      'method'  => 'POST',
      'content' => $query_content
    ]
  ]));
  if ($fp === FALSE) {
    return json_encode(['error' => 'Failed to get contents...']);
  }
  $result = stream_get_contents($fp); // no maxlength/offset
  fclose($fp);
  return $result;
}

1
이 CURL-less 방법은 Google에서 reCAPTCHA의 유효성을 검사하는 데 효과적이었습니다. 이 답변이 구글 코드로 수렴 : github.com/google/recaptcha/blob/master/src/ReCaptcha/...
사비 몬테로

1
is 인 fclose()경우 사용할 필요 $fp가 없습니다 false. 때문에 fclose()예상하는 자원 매개 변수입니다.
Floris

1
@Floris 지금 막 편집했고 실제로 fclose 문서 에는 "파일 포인터가 유효해야합니다"라고 언급되어 있습니다. 그것을 알아 주셔서 감사합니다!
CPHPython

8

더 나은 보내기 GET또는 POST요청 방법 PHP은 다음과 같습니다.

<?php
    $r = new HttpRequest('http://example.com/form.php', HttpRequest::METH_POST);
    $r->setOptions(array('cookies' => array('lang' => 'de')));
    $r->addPostFields(array('user' => 'mike', 'pass' => 's3c|r3t'));

    try {
        echo $r->send()->getBody();
    } catch (HttpException $ex) {
        echo $ex;
    }
?>

코드는 공식 문서 http://docs.php.net/manual/da/httprequest.send.php 에서 가져 왔습니다.


1
@akinuri 강조해 주셔서 감사합니다. 새로운 것을 공유하겠습니다.
Imran Zahoor

PHP 5x에서 어떻게합니까?

@YumYumYum이 기술을 사용하는 5x에 대한 위의 dbau의 답변을 확인하십시오 php.net/manual/en/function.stream-context-create.php 또는 항상 표준 컬 솔루션으로 돌아갈 수 있습니다.
Imran Zahoor

5

사용할 수있는 것이 하나 더 있습니다

<?php
$fields = array(
    'name' => 'mike',
    'pass' => 'se_ret'
);
$files = array(
    array(
        'name' => 'uimg',
        'type' => 'image/jpeg',
        'file' => './profile.jpg',
    )
);

$response = http_post_fields("http://www.example.com/", $fields, $files);
?>

자세한 내용은 여기를 클릭하십시오


2
이것은 대부분 설치되지 않은 PECL 확장에 의존합니다. 매뉴얼 페이지가 제거되었으므로 여전히 사용 가능한지 확실하지 않습니다.
miken32

5

나는 비슷한 문제를 찾고 있었고 이것을하는 더 나은 접근법을 발견했다. 그래서 여기에 간다.

리디렉션 페이지 (예 : page1.php)에 다음 줄을 추가하면됩니다.

header("Location: URL", TRUE, 307); // Replace URL with to be redirected URL, e.g. final.php

REST API 호출에 대한 POST 요청을 리디렉션하려면 이것이 필요 합니다. 이 솔루션은 사용자 지정 헤더 값뿐만 아니라 게시 데이터로 리디렉션 할 수 있습니다.

참조 링크 는 다음과 같습니다 .


1
이 답변은 어떻게하는 페이지 요청을 리디렉션 하지 내가 PHP와 POST 요청을 보내 어떻게해야합니까? 물론 이것은 모든 POST 매개 변수를 전달하지만 전혀 같은 것은 아닙니다
Wesley Smith

DelightedD0D @, 미안해 차이하지 않았다 redirect a page request with POST param대를 send POST request. 나를 위해 둘 다의 목적은 동일합니다. 틀린 경우 수정하십시오.
Arindam Nayak

1
POST 방법으로 매개 변수를 보내고 PHP를 통해 내용을 읽을 수있는 방법이 있습니까? OP는 그들의 PHP 스크립트가 POST 매개 변수 세트를 구성하고이를 다른 PHP 페이지로 보내고 스크립트가 해당 페이지의 출력을 수신하기를 원합니다. 이 솔루션은 이미 POST 된 값 집합을 수락하여 다른 페이지로 전달합니다. 그들은 매우 다릅니다.
웨슬리 스미스

5

여기에 cURL없이 하나의 명령 만 사용합니다. 매우 간단합니다.

echo file_get_contents('https://www.server.com', false, stream_context_create([
    'http' => [
        'method' => 'POST',
        'header'  => "Content-type: application/x-www-form-urlencoded",
        'content' => http_build_query([
            'key1' => 'Hello world!', 'key2' => 'second value'
        ])
    ]
]));

Key2는 어떻게 작동합니까? 그들 사이의 분리기는 무엇입니까?
무함마드 Idrees 말했다

@Sayedidrees 키 2를 추가하려면 두 번째 배열 항목으로 입력 할 수 있습니다. '키 1'=> '안녕하세요 세계!', '키 2'=이> '두 번째 값'
리가

이것은 zapier와 함께 사용하는 동안 매우 잘 작동합니다.
Moxet 1

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