file_get_contentsが動かないときの対策【PHP】

PHPでSSL(https)サイトのコンテンツを取得できない【file_get_contents】 プログラミング

「SSLサイトのコンテンツが取得できない!」
「いきなり外部コンテンツを取得できなくなった・・・」
「file_get_contentsでエラーが出ている・・・」

このように困っていませんか?
おそらく、この記事に来たということは上記のように困っているのかもしれません。

あらかじめ伝えておきます。
この記事で取り扱う内容は、PHPで開発されたシステムやプログラムが対象です。

そして、この記事の読者は以下を想定しています。

  • file_get_contentsでエラーが発生して困っている人
  • 利用中のシステム(WrordPressなど)が突然外部コンテンツを取得できなくなって困っている人

上記の人々がこの記事を読めば、次のメリットを得られます。

  • file_get_contentsのエラーを解消できるようになる
  • 利用中のシステムが外部コンテンツを取得できるようになる

本記事の内容

  • file_get_contentsのエラー内容を確認
  • file_get_contentsのエラー解消方法
  • file_get_contentsのエラーの根本解決の是非

この記事を書いている私は、PHPでの開発歴10年以上のエンジニアです。
現在は、6回の転職を経て、大手企業でサラリーマンをしています。

  • 開発したシステムは50以上
  • フルスクラッチが得意でサーバ構築からフロント開発まで対応可能
  • 副業収入2000万円以上、毎月10万の安定収入あり

本業、副業の両方でもPHPとの関係は長いです。
その長い経験の中でも、file_get_contentsには結構悩まされてきました。

今現在、またはこれからにおいてもfile_get_contentsで悩む人は出てくると思います。
そういった人々の手助けになればと思い、この記事を作成しています。

それでは、本文を説明していきます。

file_get_contentsのエラー内容を確認

エラーの確認

最初に、現状を確認します。
コンテンツ取得に失敗しているのが、本当にfile_get_contentsのエラーによるものかどうかを確認します。

エラーログを見ると言う方法があります。
しかし、誰もがエラーログを見ることができるわけではありません。

そのため、簡単に確認するために次のプログラムを動かしてください。

<?php
    ini_set('display_errors', "On");
    
    //取得したいコンテンツのURL(置き換えてください)
    $target_url = "https://example.com";
    
    file_get_contents($target_url);

?>

まずは、check.phpという名前のファイルを作成します。
上記内容をすべてcheck.phpにコピーします。

そして、PHPを動かすことのできる場所にcheck.phpを設置します。
面倒なら、ドキュメントroot直下でもOKです。

では、確認です。
check.phpにアクセスしてください。

https:// あなたのサイトのドメイン/check.php
※上記URLはroot直下にchekc.phpを設置した場合のURLです。

もし、何も表示されないなら、file_get_contentsが原因のエラーではないですね。
もちろん、可能性はゼロとは言いませんが、他の原因を追究した方がよいでしょう。

さて、次のようにいろいろと表示されたでしょうか?
確認できている範囲では、次の2パターンのエラーを確認できています。

Warning: file_get_contents(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed in ファイルを置いたディレクトリパス/check.php on line 7

Warning: file_get_contents(): Failed to enable crypto in ファイルを置いたディレクトリパス/check.php on line 7

Warning: file_get_contents(取得先のURL): failed to open stream: operation failed in ファイルを置いたディレクトリパス/check.php on line 7
Warning: file_get_contents(): SSL operation failed with code 1. OpenSSL Error messages: error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed in  ファイルを置いたディレクトリパス/check.php on line 7

Warning: file_get_contents(): Failed to enable crypto in  ファイルを置いたディレクトリパス/check.php on line 7

Warning: file_get_contents(取得先のURL): failed to open stream: operation failed in  ファイルを置いたディレクトリパス/check.php on line 7

それぞれにおける違いは、次の箇所ですね。

  • 14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE
  • 1416F086:SSL routines:tls_process_server_certificate:certificate

上記の2パターンのうち、どちらかが表示された場合は解消できるエラーです。

file_get_contentsのエラー解消方法

とても、簡単です。
check.phpを修正して、エラーを解消します。

file_get_contents($target_url);

↓↓↓

$options = stream_context_create(array('ssl' => array(
  'verify_peer'      => false,
  'verify_peer_name' => false
)));

file_get_contents($target_url, false, $options);

このように変更するだけです。
変更内容を簡単に説明すると、「証明書エラーは無視します」という宣言を加えただけです。

無視して、コンテンツを取得します。
これで、コンテンツを取得できるようになります。

ただ、これは小手先の対応です。
いわゆる、対処療法ですね。

証明書のエラーが出ないようになったわけではありません。
根本的な問題は、残ったままということです。

しかし、根本的な問題をプログラマーやシステム利用者が追いかける必要はありません。
それに関しては、次で説明します。

file_get_contentsのエラーの根本解決の是非

根本的な問題は、解決できない可能性が多いにあります。

そもそも、証明書に関しては、相手側サーバーの問題でもあるのです。
アクセスするこちら側の問題でもありえるし、相手側の問題でもありえるということです。

どっちに問題があるのか、これを判別するのも簡単ではありません。
判別できたところで、相手側の問題であれば、どうしようもありません。

こちら側に問題があった場合でも、簡単な話ではありません。
OpenSSLのバージョン、自サーバー上の証明書、PHPのバージョンなどに原因が考えられます。

レンタルサーバなら、何もできないでしょう。
サーバーを触れるとしても、簡単にソフトのバージョン変更などはできません。

いろいろと書きましたが、根本的な問題を解決するのには手間がかかり過ぎます。
問題を解決する労力が得られるリターンに比べて、大き過ぎるのです。

それであるならば、根本的な問題解決は不要です。
つまり、対症療法まではいらないと言うことです。

まとめ

file_get_contentsのエラーを解消する方法を説明しました。
たった数行追加するだけでエラーを解消できるなら、それで十分です。

何でもかんでも根本的な解決を図る必要はありません。
それがのちのちに大きな問題になりえるなら、コストをかけてでも解決を目指すべきでしょう。

しかし、対処療法で問題なく事が進むなら、対症療法は必要ありません。

エンジニアは、ついつい好奇心から対症療法をやりがちなんですよね。
でも、費用対効果を意識すれば、そのようなことをしていられません。

タイトルとURLをコピーしました