PHP + curl, HTTP POST 샘플 코드?


491

누구든지 HTTP POST로 PHP curl을 수행하는 방법을 보여줄 수 있습니까?

다음과 같은 데이터를 보내려고합니다.

username=user1, password=passuser1, gender=1

www.domain.com

컬이와 같은 응답을 반환 할 것으로 기대합니다 result=OK. 예가 있습니까?

답변:


840
<?php
//
// A very simple PHP example that sends a HTTP POST to a remote site
//

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL,"http://www.example.com/tester.phtml");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,
            "postvar1=value1&postvar2=value2&postvar3=value3");

// In real life you should use something like:
// curl_setopt($ch, CURLOPT_POSTFIELDS, 
//          http_build_query(array('postvar1' => 'value1')));

// Receive server response ...
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$server_output = curl_exec($ch);

curl_close ($ch);

// Further processing ...
if ($server_output == "OK") { ... } else { ... }
?>

47
http_build_query()매개 변수를 처리하는 데 사용할 필요가 없습니다 . 배열을 전달하면 CURLOPT_POSTFIELDS충분합니다.
랩터

8
CURLOPT_POSTFIELDS에 직접 배열을 제공하는 @Raptor 실제로 curl은 약간 다른 POST 유형을 만듭니다. (예상 : 100- 연속)
Oleg Popov

22
또한 값이 CURLOPT_POSTFIELDS배열 인 경우 Content-Type헤더 multipart/form-data대신에 헤더가 설정됩니다 application/x-www-form-urlencoded. php.net/manual/en/function.curl-setopt.php
Chloe

2
CURLOPT_RETURNTRANSFER를 사용하면 curl_exec가 응답을 출력하지 않고 문자열로 반환합니다.
bnp887

2
for true대신에 사용 하는 것이 좋습니다 . 1CURLOPT_POST
FluorescentGreen5 5

261

절차 적

// set post fields
$post = [
    'username' => 'user1',
    'password' => 'passuser1',
    'gender'   => 1,
];

$ch = curl_init('http://www.example.com');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);

// execute!
$response = curl_exec($ch);

// close the connection, release resources used
curl_close($ch);

// do anything you want with your response
var_dump($response);

객체 지향

<?php

// mutatis mutandis
namespace MyApp\Http;

class CurlPost
{
    private $url;
    private $options;

    /**
     * @param string $url     Request URL
     * @param array  $options cURL options
     */
    public function __construct($url, array $options = [])
    {
        $this->url = $url;
        $this->options = $options;
    }

    /**
     * Get the response
     * @return string
     * @throws \RuntimeException On cURL error
     */
    public function __invoke(array $post)
    {
        $ch = curl_init($this->url);

        foreach ($this->options as $key => $val) {
            curl_setopt($ch, $key, $val);
        }

        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post);

        $response = curl_exec($ch);
        $error    = curl_error($ch);
        $errno    = curl_errno($ch);

        if (is_resource($ch)) {
            curl_close($ch);
        }

        if (0 !== $errno) {
            throw new \RuntimeException($error, $errno);
        }

        return $response;
    }
}

용법

// create curl object
$curl = new \MyApp\Http\CurlPost('http://www.example.com');

try {
    // execute the request
    echo $curl([
        'username' => 'user1',
        'password' => 'passuser1',
        'gender'   => 1,
    ]);
} catch (\RuntimeException $ex) {
    // catch errors
    die(sprintf('Http error %s with code %d', $ex->getMessage(), $ex->getCode()));
}

여기에서 참고 사항 : AdapterInterface예를 들어 getResponse()메소드로 호출되는 인터페이스를 작성하고 위의 클래스가 구현하도록하는 것이 가장 좋습니다 . 그런 다음 응용 프로그램에 아무런 부작용없이 항상이 구현을 원하는 다른 어댑터로 바꿀 수 있습니다.

HTTPS 사용 / 트래픽 암호화

일반적으로 Windows 운영 체제에서 PHP의 cURL에 문제가 있습니다. https로 보호 된 엔드 포인트에 연결하려고 할 때 오류 메시지가 표시 certificate verify failed됩니다.

대부분의 사람들이 여기서하는 일은 cURL 라이브러리에 단순히 인증서 오류를 무시하고 계속하도록 지시하는 것입니다 ( curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);). 이렇게하면 코드가 작동하므로 악의적 인 사용자가 Man In The Middle 공격 등과 같은 다양한 공격을 앱에서 수행 할 수 있습니다 .

절대로 그렇게하지 마십시오. 대신, 당신은 단순히 당신을 수정 php.ini하고 CA Certificate파일이 인증서를 올바르게 확인할 수 있도록 PHP 에게 알려 주면됩니다 :

; modify the absolute path to the cacert.pem file
curl.cainfo=c:\php\cacert.pem

cacert.pem인터넷에서 최신 버전 을 다운로드하거나 즐겨 찾는 브라우저에서 추출 할 수 있습니다 . php.ini관련 설정을 변경할 때는 웹 서버를 다시 시작해야합니다.


4
최선의 방법은 HTTP 라이브러리가 변수의 인코딩을 처리하도록하는 것이기 때문에 이것이 실제로 허용되는 답변이어야합니다.
Eric Seastrand

4
항상 그런 것은 아닙니다. POST 변수가 특정 방식으로 인코딩되어 웹 서버가 실패하는 웹 서버를 보았습니다. http_build_query ()이 실제로 cURL보다 더 신뢰할 수있는 것 같습니다.
César

4
HTTP 사양은 POST 매개 변수의 모양에 대해 매우 간단합니다. 웹 서버 소프트웨어는 어쨌든 표준을 준수해야합니다.
emix

1
이 방법을 사용하면 cURL이 약간 다른 유형의 POST를 사용하게됩니다. (예상 : 100- 연속). 이 기사를 확인하십시오 : support.urbanairship.com/entries/…
Oleg Popov

5
@ César의 의견을 확대하여 PHP 문서 는 다음과 같이 명시 적으로 언급합니다. "CURLOPT_POSTFIELDS에 배열을 전달하면 데이터가 multipart / form-data 로 인코딩되고 URL로 인코딩 된 문자열을 전달하면 데이터가 application / x-www-form 으로 인코딩 됩니다 -urlencoded . ". 최근에 cURL 호출이 타사 엔드 포인트에서 실패하여 멀티 파트 / 폼 데이터를 지원하지 않았다는 사실을 깨닫기 위해 문제를 해결하는 데 상당한 시간을 소비했습니다.
Jake Z

31

php curl_exec를 사용하여 HTTP 게시를 수행하는 실제 예 :

이것을 foobar.php라는 파일에 넣으십시오.

<?php
  $ch = curl_init();
  $skipper = "luxury assault recreational vehicle";
  $fields = array( 'penguins'=>$skipper, 'bestpony'=>'rainbowdash');
  $postvars = '';
  foreach($fields as $key=>$value) {
    $postvars .= $key . "=" . $value . "&";
  }
  $url = "http://www.google.com";
  curl_setopt($ch,CURLOPT_URL,$url);
  curl_setopt($ch,CURLOPT_POST, 1);                //0 for a get request
  curl_setopt($ch,CURLOPT_POSTFIELDS,$postvars);
  curl_setopt($ch,CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch,CURLOPT_CONNECTTIMEOUT ,3);
  curl_setopt($ch,CURLOPT_TIMEOUT, 20);
  $response = curl_exec($ch);
  print "curl response is:" . $response;
  curl_close ($ch);
?>

그런 다음 명령으로 실행하면 php foobar.php이런 종류의 출력을 화면에 덤프합니다.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" 
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Title</title>

<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
<body>
  A mountain of content...
</body>
</html>

www.google.com에 PHP POST를 수행하여 데이터를 보냈습니다.

서버가 사후 변수를 읽도록 프로그래밍 된 경우,이를 기반으로 다른 작업을 수행 할 수 있습니다.


$postvars .= $key . $value;해야 $postvars .= $key . $value ."&";합니까?
Manwal

이 답변을 다시 살펴보면 사용자 정의 쿼리 문자열 변환기 구현을 http_build_query 로 대체 하고 $fields배열을 제공 하면 쿼리 문자열이 출력됩니다.

데이터를 안전하게 제출하려면 데이터를 인코딩해야합니다.
wtf8_decode

3
아뇨 포스트 문자열을 직접 만들려고하지 마세요! 이것을 사용하십시오 :curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($fields));
oriadam

3
게시물 변수를 벗어나지 않기 때문에 -1입니다. OP의 예는 인증을 위해 사용자가 제출 한 사용자 이름과 비밀번호를 보내는 것입니다. 솔루션을 사용하면 비밀번호가 & 인 사용자는 절대 로그인 할 수 없습니다. oriadam의 의견은 정확하지만 다음 http_build_query과 같이 탈퇴 할 수 있습니다 .curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
Eric Seastrand

26

다음과 같이 쉽게 도달 할 수 있습니다.

<?php

$post = [
    'username' => 'user1',
    'password' => 'passuser1',
    'gender'   => 1,
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://www.domain.com');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post));
$response = curl_exec($ch);
var_export($response);

13

컬 포스트 + 오류 처리 + 헤더 설정 [@ mantas-d 덕분에] :

function curlPost($url, $data=NULL, $headers = NULL) {
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    if(!empty($data)){
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    }

    if (!empty($headers)) {
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    }

    $response = curl_exec($ch);

    if (curl_error($ch)) {
        trigger_error('Curl Error:' . curl_error($ch));
    }

    curl_close($ch);
    return $response;
}


curlPost('google.com', [
    'username' => 'admin',
    'password' => '12345',
]);

예외가 발생한 후 curl_close를 수행하므로 코드에서 핸들을 닫고 리소스를 해제하지 않습니다. finally 블록 안에 curl_close가 있어야합니다.
emix

7
curlPost('google.com', [
    'username' => 'admin',
    'password' => '12345',
]);


function curlPost($url, $data) {
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    $response = curl_exec($ch);
    $error = curl_error($ch);
    curl_close($ch);
    if ($error !== '') {
        throw new \Exception($error);
    }

    return $response;
}

1
예외가 발생한 후 curl_close를 수행하므로 코드에서 핸들을 닫고 리소스를 해제하지 않습니다. 당신은 블록 curl_close안에 있어야합니다 finally.
emix

6

양식이 리디렉션, 인증, 쿠키, SSL (https) 또는 POST 변수를 예상하는 완전히 열린 스크립트 이외의 것을 사용하는 경우 치아를 빨리 gn 기 시작할 것입니다. Snoopy를 살펴보면 , 많은 오버 헤드를 설정할 필요없이 정확히 생각하고있는 것을 수행 할 수 있습니다.


스톡 라이브러리를 고수하려면 다음을 추가하십시오.curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
MarkHu

유일한 단점은 쿠키 항아리 및 기타 잠재적 문제 (리디렉션 수행 여부, 비 HTTP 기반 인증 처리 방법 등) 설정을 처리해야한다는 것입니다. 6 년 후, 나는 특정 라이브러리 (또는 소스 포지에있는 것, 날짜가 얼마나 되었습니까?) 대신 "헤드리스 브라우저"의보다 일반적인 개념을 추천 할 것입니다. 그리고 일반적으로 컬 옵션을 직접 처리하는 동안 여전히 조언 할 것입니다. 두통을 피하기 위해 PSR-7 과 호환 되는 헤드리스 브라우저 라이브러리 (Guzzle은 내가 아는 유일한 것)를 찾고 있습니다.
Anthony

3

자신의 웹 사이트에 정보를 전달하는 경우 더 간단한 답변 SESSION 변수를 사용하는 것입니다. 다음을 사용하여 PHP 페이지를 시작하십시오.

session_start();

어느 시점에서 PHP에서 생성하고 POST 변수를 사용하는 대신 세션의 다음 페이지로 전달하려는 정보가 있으면 SESSION 변수에 지정하십시오. 예:

$_SESSION['message']='www.'.$_GET['school'].'.edu was not found.  Please try again.'

다음 페이지에서이 SESSION 변수를 참조하십시오. 참고 : 사용 후에는 반드시 폐기하여 사용 후에도 지속되지 않도록하십시오.

if (isset($_SESSION['message'])) {echo $_SESSION['message']; unset($_SESSION['message']);}

3

다음은 PHP + curl에 대한 상용구 코드입니다. http://www.webbotsspidersscreenscrapers.com/DSP_download.php

이 라이브러리에 포함하면 개발이 간단 해집니다.

<?php
# Initialization
include("LIB_http.php");
include("LIB_parse.php");
$product_array=array();
$product_count=0;

# Download the target (store) web page
$target = "http://www.tellmewhenitchanges.com/buyair";
$web_page = http_get($target, "");
    ...
?>

2

쿠키를 사용하여 사이트에 로그인하려고하면

이 코드는 :

if ($server_output == "OK") { ... } else { ... }

많은 사이트가 상태 200을 반환하지만 게시에 실패하여 로그인을 시도하면 작동하지 않을 수 있습니다.

로그인 게시물이 성공적인지 확인하는 쉬운 방법은 쿠키를 다시 설정하는지 확인하는 것입니다. 출력에 Set-Cookies 문자열이 있으면 게시가 실패하고 새 세션이 시작됨을 의미합니다.

또한 게시물은 성공할 수 있지만 상태는 200 대신 리디렉션 될 수 있습니다.

게시물이 성공했는지 확인하려면 다음을 시도하십시오.

게시물 뒤 위치를 따라 가면 게시물이 리디렉션되는 페이지로 이동합니다.

curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

요청에 새로운 쿠키가 있는지 확인하십시오.

if (!preg_match('/^Set-Cookie:\s*([^;]*)/mi', $server_output)) 

{echo 'post successful'; }

else { echo 'not successful'; }

1

양식원시 데이터 전송의 예 :

$curlHandler = curl_init();

curl_setopt_array($curlHandler, [
    CURLOPT_URL => 'https://postman-echo.com/post',
    CURLOPT_RETURNTRANSFER => true,

    /**
     * Specify POST method
     */
    CURLOPT_POST => true,

    /**
     * Specify array of form fields
     */
    CURLOPT_POSTFIELDS => [
        'foo' => 'bar',
        'baz' => 'biz',
    ],
]);

$response = curl_exec($curlHandler);

curl_close($curlHandler);

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