🐘

PHP8にアプデしたらcurl_setoptのCURLOPT_COOKIEJARでCookieを保存できなくなった時の対処法

2024/03/10に公開

事象

php8以前では、curl_setopt関数でCURLOPT_COOKIEJARのオプションをセットして、cookieを保存できていたができなくなった。
file_existを実行するとファイルの存在は確認できるが、中身が空の状態。

結論

CURLプロセスを終了するときに、curl_close($ch)ではなく、unset($ch)を使う。

原因

COOKIEJARによるCookieの保存は、CURLプロセスが終了した時に書き込まれるが、PHP8からCURLプロセスの終了方法が変わっていました。より正確に言うと、curl_init()の返り値が変わったようです。

変更履歴 ¶
バージョン 説明
8.0.0 成功時に、この関数は CurlHandle クラスのインスタンスを返すようになりました。 これより前のバージョンでは、resource を返していました。

https://www.php.net/manual/ja/function.curl-init.php

この変更により、curl_close($ch)ではCURLプロセスが終了できなくなりました。PHPのドキュメントのcurl_closeの説明には

注記:
この機能は効果がありません。PHP 8.0.0 より前では、この関数はリソースを閉じるために使用されていました。

https://www.php.net/manual/ja/function.curl-close.php
とあります。
そのため、プロセスを終了させるのにunset($ch)を使用するとCookieが保存されるようになりました。

サンプルコード

   // 一時フォルダにCookie保存するためのパスを定義
   $cookieFile = tempnam(sys_get_temp_dir(),"cookie_test_");

   // cURLのオプション設定と実行
    $ch = curl_init($url);
  curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);  
  curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);  
  curl_setopt($ch, CURLOPT_COOKIEJAR, $cookieFile);
  curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);

  $output = curl_exec($ch);
  // curl_close($ch); これをunset()に変える
  unset($ch);
  var_dump(file($cookieFile));

※ COOKIEJAR以外のオプションは適当です。

参考

https://stackoverflow.com/questions/72434796/php-curl-cookie-not-saved-after-curl-close

Discussion