FILE_GET_CONTENTが動作しない?

PHP
この記事は約8分で読めます。

WordPressで外部リンクを「はてなブログカード」に置き換えて表示させるプラグイン「Pz-HatenaBlogCard」のver1.2.1を公式プラグインディレクトリにて公開したところ、さっそくご意見をいただいたので調べてみました。

ソーシャルカウントの取得方法

ソーシャルカウントの取得には、FILE_GET_COUNTを使って、ソーシャルカウント取得APIから値を取得しています。

ちなみに「Syncer」さんの「ソーシャルカウント取得方法まとめ」を参考にさせていただきました。

ツイッターの場合、APIを叩くとJSON形式で返してくるので、それを配列に入れておきます。

$json = json_decode( @file_get_contents( 'http://urls.api.twitter.com/1/urls/count.json?url='.rawurlencode($url)), true );

そこから、「count」を取得して、空っぽだったら「0」をセットしています。

「file_get_contents」の前に「@」(アットマーク)が付いているのは、「エラー出てもエラー吐かずにスルーしてね」という意味です。

$count = isset($json['count']) ? $json['count'] : 0 ;

そして、取得したカウントが0より多かったら、カウントの表示をしています。

if ($count > 0 ) {
    $domain_info .= '<span class="linkcard-sns-twitter">'.$count.' tweet'.(($count > 1) ? 's' : '').'</span>';
}

「(($count > 1) ? ‘s’ : ”)」っていうところで、1だったら「1 tweet」、2以上だったら「2 tweets」と、「s」を付けるようにしています。

 

さて、「はてなブックマーク数やツイート数が取得できない」という話をいただきました。

そちらのサイトさんを見に行くと確かにカウントが表示されていませんでした。

no-count

自分のテストサイトを使って同じURLでブログカードをつくってみると、ちゃんとカウント数が表示されます。

1use-63shares-33tweets

「(外部サイト)」と表示されているので、「はてなブログカード」では無くオリジナル形式で表示されているようです。

また、設定画面のハードコピーもいただいたので、設定も問題無さそうです。

GET_FILE_CONTENTSが使えない?

サーバー内のファイルも開ければ、URLを指定すればHTMLも取得できる「get_file_contents」ですが、どうやらphpの設定によってはURL指定が出来ないらしいです。

php.ini を編集することで、有効にできるようです。

allow_url_fopen = On

信頼できないファイルを取得してしまう場合があるので、安全性を取るか利便性を取るかみたいなところなんだと思います。

レンタルサーバーなどによっては php.ini を編集できない場合もあるので、今回は別の取得方法を検討してみます。

cURLなら取得できそう

「記述がラクで、少ない行数で書けるかなぁ」という考えでget_file_contentsを使っていたのですが、cURLを使った方が良さそうです。

cURLは、あたかもブラウザでサイトを見に行ったようなことができる関数です。

使いこなしたらスクレイピングみたいなことは何でも出来そうな気がします。

wp_remote_getも使えそう

WordPressの関数で、「安全なHTML取得」みたいなのがあったと思ったのですが、思い出せず。

調べてみたところ、探していたのは「wp_remote_get」関数だったようです。

「安全な」というフレーズをどこで見たのかは分かりませんが、今回はこれを使ってみようと思います。

書き換えてみる

ツイート数を例に。

変更前は、file_get_contents で body を取得しつつも json_decode で連想配列方式に変換。

連想配列から「count」を取得して、0より上ならカウントを表示しています。

$json = json_decode( @file_get_contents( 'http://urls.api.twitter.com/1/urls/count.json?url='.rawurlencode($url)), true );
$count = isset($json['count']) ? $json['count'] : 0 ;
if ($count > 0 ) {
    $domain_info .= '<span class="linkcard-sns-twitter">'.$count.' tweet'.(($count > 1) ? 's' : '').'</span>';
}

基本的には file_get_contents を wp_remote_get に置き換えます。

file_get_contents は、body を直接返してくれましたが、wp_remote_get の場合はステータスとかも込みで連想配列で返してくれます。

いったん配列に入れて「body」を取り出すために1行増えています。

$array = wp_remote_get( 'http://urls.api.twitter.com/1/urls/count.json?url='.rawurlencode($url) );
$json = json_decode( (isset($array['body']) ? $array['body'] : null), true );
$count = ( (isset($json['count']) ? $json['count'] : 0) );
if ($count > 0 ) {
    $domain_info .= '<span class="linkcard-sns-twitter">'.$count.' tweet'.(($count > 1) ? 's' : '').'</span>';
}

同じ結果が表示されたのを確認しました。

 

「取得エラー時の処理を書いてないけど、大丈夫かな!Σ(゚ロ゚)o゙」と思いましたが…。

大丈夫じゃありませんでしたΣ(゚ロ゚)o゙

 

相手サイトが落ちてたりすると、こっちもエラーが出てしまうようです。

おち研」さんのところに、wp_remote_get を使ってシンプルにソーシャルカウントを取る方法がありました。

wp_remote_get をしたあとに、isset でセットされていること、wp_error でエラーを確認して、jsonデコードしつつも値をセットして、0を引くことで数値にしちゃう感じです。

$array = wp_remote_get( 'http://urls.api.twitter.com/1/urls/count.json?url=' .rawurlencode($url) );
if (isset($array) && !is_wp_error($array)) {
    $count = json_decode($array['body'])->count - 0;
    if ($count > 0 ) {
        $domain_info .= '<span class="linkcard-sns-twitter">'.$count.' tweet'.(($count > 1) ? 's' : '').'</span>';
    }
}

相手サイトが落ちていても、wp_error で引っかかるので大丈夫そうです。(適当なアドレスに書き換えたとき、シェア数0として動作しました。)

とりあえずリリースしてみます

一応テストサーバーがあって、過去に報告をいただいた方が使っているテーマやらプラグインを入れた環境でテストするように心掛けてはいるものの、環境のパターンは無数にあって難しいです(^-^;

でも、リリースするたびに、色々言ってもらって、新しい発見があったりするのは嬉しいです。

トラブルシューティングも楽しいので良いのですが、安定して使いたい方のところで止まってしまうとあせってしまいますね(^-^;

というわけで、準備でき次第、ver1.2.2 としてリリースします。

コメント

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