スタッフブログ

  • 最新配信
  • RSS

do-whileでエラー遷移を制御する

 : PHP 2008/7/16 2:04

Blogger's Avatar

PHP4の最終リリースもせまり、もうPHP4を触る事はないだろうと思っていたのになぜかPHP4のコードを書いているhaltです。 今日はPHP4でのエラー遷移制御のバッドノウハウ…いやテクニックを紹介します。 通常、エラー発生時にメッセージを貯めていくコードを書くと、以下のような感じになり がちです。
class example1_controller
{
    function post()
    {  
        $comma_count = 3;
        $filename = __FILE__;
        if (file_exists($filename)) {
            if ($filedata = file_get_contents($filename)) {
                $csv_data = array();
                $rows = explode("\n", $filedata);
                array_shift($rows); //先頭行はタイトルなのでイラネ
                if (count($rows) < 1) {
                    $this->error->addError('parse error.');
                } else {
                    foreach ($rows as $row) {
                        $cols = explode(',', $row);
                        if (count($cols) != 4) {
                            $this->error->addError('invalid column count.');
                            break;
                        }
                        $csv_data[] = $cols;
                    }
                }
            } else {
                $this->error->addError('file read failed.');
            }
        } else {
            $this->error->addError('target file not found.');
        }

        // 途中でエラーがあってもここを通したい
        $this->render->setAttribute('error', $this->error);
        $this->render->setTemplate('test.tpl');
    }
}
「エラーがなければ次へ」というifを繰り返して先へ進むこのコードですがネストが深く なってしまいたいへん見辛いコードになっています。 PHP5なら、tryブロックで囲んでエラーが発生したらthrowする事で、ネストする事なしに 処理をとばせるのですが、PHP4にはtry-catch構文がないので仕方なくif文で…となると>>立ちまち汚いコードがうまれてしまいます。 そこで他の人はどうやっているのだろうと検索してみたところ、一回で抜けるようにした do-while文を使ってtryブロックのように囲み、問題が発生した時点でbreakする事によっ て擬似的にtry-catchのような遷移を実現するという方法を知りました。 あきらかにクセがあるので使うタイミングを良く考える必要がありそうですが、具体的に は以下のような感じです。
class example2_controller
{
    function post()
    {
        $comma_count = 3;
        $filename = __FILE__;

        do {
            if (!file_exists($filename)) {
                $this->error->addError('target file not found.');
                break;
            }

            $filedata = file_get_contents($filename);
            if ($filedata === false) {
                $this->error->addError('file read failed.');
                break;
            }

            $csv_data = array();
            $rows = explode("\n", $filedata);

            array_shift($rows); //先頭行はタイトルなのでイラネ
            if (count($rows) < 1) {
                $this->error->addError('parse error.');
                break;
            }

            foreach ($rows as $row) {
                $cols = explode(',', $row);
                if (count($cols) != 4) {
                    $this->error->addError('invalid column count.');
                    break;
                }
                $csv_data[] = $cols;
            }
        } while(0);

        // 途中でエラーがあってもここを通したい
        $this->render->setAttribute('error', $this->error);
        $this->render->setTemplate('test.tpl');
    }
}
do-whileブロック内では、エラー発生時点でbreakを使って処理を抜けている為、if文連>打のようにネストが深くなる事はありません。do-whileテクニックを知っている人が見れ ば非常に見易いでしょう。ただし、ネスト回数の少ないコードでこれを使うと意図が見え づらく、混乱の元になりそうです。 クラスなどを利用して擬似的にExceptionを扱う方法もあるようなのですがこのあたりで>調査を終わりにしたいと思います。こういった方法を使うよりもPHP5を使った方がずっと 幸せになれるからです。

トラックバック

スタッフブログ最新
カテゴリ一覧

〒104-0061 東京都中央区銀座1丁目3番3号 G1ビル7階
お問い合わせ TEL 03-3524-8860

Copyright(c) 2012 RYUS.All Rights Reserved.