ウェブサーバから情報を取得する場合のエラー処理
「file_get_contentsとHTTP_Request、どっちがいい?」では、file_get_contentsとHTTP_Requestを比較しました。
「エラー処理を考えるとHTTP_Request」と述べたのですが、これはsimplexml_load_fileとHTTP_Requestについても言えることです。
うーん、file_get_contentsやsimplexml_load_fileを知った時は、なんてラクチン!と歓喜したものだけど、そのコストを今払っている気がする(--#
ウェブサーバを通じて情報を取得する際は、常にサーバエラーの場合の処理を書かないといけませんね。
取得したデータをもとにその場で動的に生成している場合ならまだいいんです。
一時的なサーバエラーだったらその場だけなので。
一方、定期的に取得して静的に生成する場合には、次の取得までの間エラーが表示され続けてしまいます。
外部のサーバに毎回アクセスを飛ばすことは、相手方が特に許可してない限り許されないと考えるべきです。ですから、こちらが原則でしょう。
……@で表示しないというのも手ですが、まぁそれは最後の手段ということで。
そこで、file_get_contents、simplexml_load_fileをHTTP_Requestで置き換える場合、どのように書くかが問題となります。
とりあえず自作関数?!
レスポンスコードをチェックする方法の応用編ですね。
たっくさんsimplexml_load_fileを書いていたので、自作関数にしちゃいました。
simplexml_load_fileをi_simplexml_load_fileに置き換えれば済んじゃうので(^_^;
<?php // 以上略 function i_simplexml_load_file($sourceurl) { $errorcount1 = 1; //取得回数 $errorcount2 = 3; //取得回数 3回以上だったら中断 $option = array( "timeout" => "300", //HTTP_Requestタイムアウトの秒数指定 ); do{ $req = new HTTP_Request($sourceurl, $option); // $req->setBasicAuth($GLOBALS['id'], $GLOBALS['pass']); $req->sendRequest(); if ($req->getResponseCode() == 200){ $rbody = $req->getResponseBody(); break; } else { $errorcount1++; sleep(10); //10秒間待機 } } while($errorcount1 < $errorcount2); return (simplexml_load_string($rbody)); } // 以下略 ?>
もちろん先方がレススポンスコード200を正常時に必ず返すとは限らないので、レスポンスコードに構わずとにかく2回目のリクエストにいくのはどうなの、という話もありますが、そこらへんは後で細かく詰めるということで(^^;
これで
$xml = i_simplexml_load_file("http://example.com/");
とかけば、
$xml = simpleXML_load_file("http://example.com/");
と一緒になりますね。
中身の末尾
return (simplexml_load_string($rbody));
を
return ($rbody);
に書き換えれば、file_get_contentsの場合にもいけますね。
!PEAR::isErrorってなんじゃろ
<?php require_once "HTTP/Request.php"; $req =& new HTTP_Request("http://example.com/"); if (!PEAR::isError($req->sendRequest())) { echo $req->getResponseBody(); } ?>
▽Manual :: HTTP_Request 導入
http://pear.php.net/manual/ja/package.http.http-request.intro.php
isErrorがよく出てくるので何かと思ったのですが、エラーオブジェクトを調べるそうです。
sendRequestがどういうエラーオブジェクトを返すのかわかんないんですけど……わかんないからとりあえずいれておくのか。
今回は、正常時以外は何も返して欲しくないので、いれないでおきました。
▽Manual :: PEAR の同名メソッドと同様に、エラーオブジェクトかどうかを調べる
http://pear.php.net/manual/ja/package.webservices.services-weather.services-weather.iserror.php
整形式のXMLでない場合
もう一つエラー処理といえば、整形式のXMLじゃなかったり、以前あったように制御コード入りのXMLだったりした場合に吐くパーサーエラーがあります。
しかしこれらはつぶせる限り潰したし、エラー吐かないといつまでも気付かないのでペンディング。
本当は
if(うんたらかんたら){
通常の処理
} else{
エラーをログに記録or管理者にメールで通知
}
等にして、ちゃんと気付けるようにすべき(そして利用者には見えないようにするべき)なのでしょうね。
色々なエラー処理をちょっとずつ学んでいかなければ!ですね。
エラーをぐぐると、エラーの説明を書いた記事等よりも、実際のページで出ているエラーがたくさんひっかかるんですよねぇ。