LoginSignup
14
5

More than 5 years have passed since last update.

【PHP7】 CURLOPT_POST=true を付与する場合は CURLOPT_POSTFIELDS は必須

Last updated at Posted at 2019-02-08

罠にハマってなかなか辛かったので残しておきます。

curl が飛ばない?

プロダクトの目立たない機能で API を叩いている実装があったのですが、今日になってそれが死んでいることが判明。
開発環境やステージング環境では同じコードで正常に動いているので、うーん・・・ :thinking:

調査

ということで調査。

手元で実際に叩いている URL に curl コマンドでリクエストすると正常なレスポンスが返ってきた。
本番サーバーで叩いてみても正常だった。

仕方なくプロダクトコードにログを仕込んでデプロイ。
ログを見てみると curl が false を返している :thinking:
しかも実行速度が早いのでリクエストが飛んでいない様子。

本番サーバーは最近 PHP のバージョンを 7.2 に上げたということで、開発環境とステージング環境の PHP のバージョンを確認してみたところ、 5.6 だった。
ここで、 PHP 7.2 では問題がある実装になっているのかも?と気付く。

問題のコード

こんな感じ

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $api_url);
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
$result = curl_exec($ch);

これが PHP 5.6 では動作しました。

これを PHP 7.2 の本番サーバー上で配置して実行してみると $resultfalse になります。

そもそも GET でリクエストする API なんだから CURLOPT_POST は不要では?と思い、コメントアウトしてみたところ

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $api_url);
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// curl_setopt($ch, CURLOPT_POST, true);
$result = curl_exec($ch);

正常なレスポンスが取得できました :tada:

ちなみに、 CURLOPT_POSTFIELDS を指定すると動作します。

PHP のバージョンによる違い

この POST=true, POSTFIELDS なしのコードをいくつかの環境で確認したところこんな感じでした。

動作する

  • 5.6.11
  • 5.6.26
  • 7.1.16

動作しない

  • 7.2.4
  • 7.2.14

ということで、 7.2 系ではだめっぽいです。

結論

CURLOPT_POST=true を付与する場合は CURLOPT_POSTFIELDS は必須。

PHP 7.2 にして curl がおかしくなったら疑ってみましょう。
あと、本番サーバーとステージングサーバーのバージョンは合わせましょう。

(古のコードと付き合うのはつらい)

14
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
5