PHP

PHP cURL 関数で POST フィールドに多次元配列とファイルを同時に指定する

[!NOTE]
この記事は 2012/02/01 に seijimomoto.blogspot.com/2012/02/php-curlpost.html へ投稿した内容を Qiita へ移行してきたものです
この記事では PHP 5.5.0 以降で有効な CURLOPT_SAFE_UPLOADCURLFile について言及されていません

 PHP がサポートする cURL 関数をつかって POST フィールドに配列データとファイルを同時に指定してリクエストを送信します。

POST フィールドにファイルだけを指定する場合

 ファイルを指定するだけであれば、curl_setopt のドキュメントでも説明されているように、先頭に @ プレフィクスをつけたファイルパスを配列に格納してcURLセッションハンドルのオプションに設定します。

 例えば、フィールド名は "filedata" で /tmp/hoge.txt をアップロードしたいときは下のようになります:

POSTフィールドにファイルだけを指定する
$postfields = array("filedata"=>"@/tmp/hoge.txt;type=text/plain");

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://localhost/");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);
curl_exec($ch);

POST フィールドに配列データだけを指定する場合

 上の例とは別に、POST フィールドに配列だけを指定する場合、例えば、フィールド名は "postdata" で配列 [ 'A', 'B', 'C' ] を送信するときは...

Notice-Array-to-string-conversion
$postfields = array("postfields" => array('A', 'B', 'C'));

// Notice:  Array to string conversion
curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);

...とできれば楽ですが curl_setopt() に渡す引数が結果的に多次元配列になると NOTICE レベルのメッセージ Array to string conversion となり、パラメーターには文字列 "Array" が格納されるため、適当なリクエストになりません。多次元配列を POST パラメーターとして送る場合、PHP の配列を HTTP の POSTパラメーター に割り当てる必要があり、次のような方法があります:

1. 配列データを文字列に書き換えて設定する(http_build_query の要領)
$postfields = "postdata[0]=A&postdata[1]=B&postdata[2]=C";

curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);
2. 一次元配列を維持したままフィールド名に添え字を付け加えて設定する
$postfields = array("postdata[0]"=>'A', "postdata[1]"=>'B', "postdata[2]"=>'C');

curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);

POSTフィールドに多次元配列とファイルを同時に指定する場合

 上の例を併せて、フィールド "filedata" にはファイル /tmp/hoge.txt を指定しながら同時に、フィールド "postdata" には配列 [ "A", "B", "C" ] を一度に設定したい場合は下のようにすることができます:

$postfields = array(
    "postdata[0]"=>'A',
    "postdata[1]"=>'B',
    "postdata[2]"=>'C',
    "filedata"=>"@/tmp/hoge.txt;type=text/plain"
);

curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);

参考