PHP + curl、HTTP POSTサンプルコード?


491

HTTP POSTでphp curlを実行する方法を誰かに教えてもらえますか?

次のようなデータを送信したい:

username=user1, password=passuser1, gender=1

www.domain.com

curlがのような応答を返すことを期待してい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で十分です。
ラプター2016

8
@Raptorが配列を直接CURLOPT_POSTFIELDSに提供すると、実際にはcurlは少し異なるタイプのPOSTを作成します。(予想:100-継続)
Oleg Popov

22
また、の値がCURLOPT_POSTFIELDS配列の場合、Content-Typeヘッダーはではmultipart/form-dataなくに設定されますapplication/x-www-form-urlencodedphp.net/manual/en/function.curl-setopt.php
クロエ

2
CURLOPT_RETURNTRANSFERを使用すると、curl_execは応答を出力するのではなく、文字列として返します。
bnp887 16

2
forのtrue代わりに使用することをお勧めします。1CURLOPT_POST
FluorescentGreen5

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場所をPHPに通知するだけですCA Certificate

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

最新のcacert.pemものはインターネットからダウンロードするか、お気に入りのブラウザから抽出できます。php.ini関連する設定を変更するときは、必ずWebサーバーを再起動してください。


4
ベストプラクティスはHTTPライブラリに変数のエンコーディングを処理させることであるため、これは実際に受け入れられる答えになるはずです。
Eric Seastrand、2016年

4
これは常にそうであるとは限りません。POST変数が特定の方法でエンコードされ、それが原因で失敗することを期待するWebサーバーを見てきました。http_build_query()は、実際にはcURLよりも信頼性が高いようです。
セザール・

4
HTTPの仕様は、POSTパラメータがどのように見えるかについては非常に単純です。いずれにしても、Webサーバーソフトウェアは標準に準拠する必要があります。
emix 2016年

1
この方法を使用することにより、cURLでわずかに異なるタイプのPOSTを使用するように強制できます。(予想:100-継続)。この記事をチェックしてください:support.urbanairship.com/entries/...
オレグ・ポポフ

5
セザールさんのコメント@を拡張し、PHPのドキュメントでは「などのデータをエンコードしますCURLOPT_POSTFIELDSに配列を渡す:明示的に以下の注意事項マルチパート/フォームデータを、URLエンコードされた文字列を渡すと、データをエンコードする一方アプリケーション/ X-WWW-フォーム-urlencoded。 "。私は最近、cURL呼び出しがサードパーティのエンドポイントで失敗した理由のトラブルシューティングに非常に多くの時間を費やし、最終的にそれらがmultipart / form-dataをサポートしていないことに気づきました。
ジェイク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を実行して、データを送信しました。

サーバーがpost変数を読み取るようにプログラムされていれば、それに基づいて別のことを実行することができます。


$postvars .= $key . $value;すべき$postvars .= $key . $value ."&";かどうか
Manwal 2014

この答えをもう一度見てみると、カスタムクエリ文字列コンバーターの実装を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);
エリック・シーストランド

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

Curlポスト+エラー処理+ヘッダーの設定[@ 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ます。
1

6

フォームがリダイレクト、認証、Cookie、SSL(https)、またはPOST変数を予期する完全に開いたスクリプト以外のものを使用している場合、歯をすぐに噛み始めるでしょう。Snoopyを見てください。Snoopyは、多くのオーバーヘッドを設定する必要をなくしながら、まさにあなたが考えていることを実行します。


ストックcurl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
ライブラリを使い続け

唯一の欠点は、cookie jarの設定やその他の潜在的な問題(リダイレクトに従うかどうか、非HTTPベースの認証の処理方法など)に対処する必要があることです。6年後、私はその特定のライブラリ(またはsourceforge上の何か、日付は正しいですか)ではなく、「ヘッドレスブラウザー」のより一般的な概念をお勧めします。通常、カールオプションを直接扱うだけですが、それでもアドバイスします頭痛の種を避けるために、PSR-7互換のヘッドレスブラウザーライブラリ(Guzzleは私が知っている唯一のものです)を調べます。
Anthony

3

自分のWebサイトに情報を渡す場合のより簡単な答えは、SESSION変数を使用することです。phpページを次のように開始します。

session_start();

ある時点で、POST変数を使用する代わりに、PHPで生成してセッションの次のページに渡したい情報がある場合は、それを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

Cookieを使用してサイトにログインしようとした場合。

このコード:

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

多くのサイトがステータス200を返すため、ログインしようとすると機能しない可能性がありますが、投稿は成功しません。

ログインポストが成功したかどうかを確認する簡単な方法は、Cookieを再度設定するかどうかを確認することです。出力にSet-Cookies文字列がある場合、これは投稿が成功せず、新しいセッションを開始することを意味します。

また、投稿は成功する可能性がありますが、ステータスは200ではなくリダイレ​​クトすることができます。

投稿が成功することを確認するには、これを試してください:

投稿の後に位置を追跡することで、投稿がリダイレクトされるページに移動します。

curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

そして、リクエストに新しいCookieが存在するかどうかを確認します。

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.