ウェブサーバから情報を取得する場合のエラー処理

「file_get_contentsとHTTP_Request、どっちがいい?」では、file_get_contentsHTTP_Requestを比較しました。
「エラー処理を考えるとHTTP_Request」と述べたのですが、これはsimplexml_load_fileHTTP_Requestについても言えることです。


うーん、file_get_contentssimplexml_load_fileを知った時は、なんてラクチン!と歓喜したものだけど、そのコストを今払っている気がする(--#




ウェブサーバを通じて情報を取得する際は、常にサーバエラーの場合の処理を書かないといけませんね。


取得したデータをもとにその場で動的に生成している場合ならまだいいんです。
一時的なサーバエラーだったらその場だけなので。


一方、定期的に取得して静的に生成する場合には、次の取得までの間エラーが表示され続けてしまいます。


外部のサーバに毎回アクセスを飛ばすことは、相手方が特に許可してない限り許されないと考えるべきです。ですから、こちらが原則でしょう。
……@で表示しないというのも手ですが、まぁそれは最後の手段ということで。



そこで、file_get_contentssimplexml_load_fileHTTP_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管理者にメールで通知
}

等にして、ちゃんと気付けるようにすべき(そして利用者には見えないようにするべき)なのでしょうね。


色々なエラー処理をちょっとずつ学んでいかなければ!ですね。
エラーをぐぐると、エラーの説明を書いた記事等よりも、実際のページで出ているエラーがたくさんひっかかるんですよねぇ。