徳丸浩の日記[PR]EGセキュアソリューションズ株式会社はエンジニアを募集しています2012年4月5日木曜日PHPの組み込み関数で例外を発生させる方法このエントリではPHPの組み込み関数でエラー時に例外を発生させる方法を紹介します。デフォルト状態では、PHPの組み込み関数の大半はエラー時に例外を発生させません。前のエントリで、PHPのheader関数は戻り値を返さず、エラー時に例外も発生させないことを紹介しました。これは酷い仕様だと思うのですが、どうすればエラーハンドリングできるかを考えてみました。header関数の場合、エラー(警告)そのものは出ているので、以下の二つの方法が候補として考えられます。error_get_last関数で直近のエラーを取得してエラー処理するset_error_handlerで定義したエラーハンドラ関数でエラー処理するどちらもモダンな書き方とはほど遠い感じです。nextを連想させますし、直近のエラーがどの箇所で起こったかは簡単には識別できないので、過去のエラーを捕捉してしまいそうです。行番号はとれますが、行番号で判断するのはよくないでしょう。これもBASICみたいですね。エラーハンドラでエラー処理するのもよくありません。エラーハンドラにはあらゆるエラーが飛んでくるので、ログを吐いてプログラムを終了させるくらいしか現実にはできないでしょう。いう問題意識で「パーフェクトPHP」を読んでおりましたら、組み込み関数から例外を発生させる方法がちゃんと書いてありました(同書P160)。エラーハンドラを設定することにより、PHPの標準のエラーを例外に変換して投げることもできます。エラーを例外に変換するには、次のようにエラーハンドラを設定します。例外の種類には、定義済みのErrorExceptionを利用しています。$errline);});PHPのパワープログラマには常識なのかもしれませんが、私は「なるほどねぇ~」と思いました。ブログ記事などでも見かけないようです。PHPのマニュアルには書いてありました。これを使って、header関数の例外処理のサンプルを書いてみました。detected.」と表示されます。いうことで、エラーを例外に変換する方法を紹介しました。パーフェクトPHPは本当に良い本ですね。これをやると、警告を含む全てのエラーで例外が発生するので、ちまたでよく見るような、エラー処理もろくにしていないヌルい書き方はできなくなり、プログラム全体できちんと例外の設計をする必要があります。本来そうあるべきですけどね。ときは例外投げないようにすれば」というコメントを頂戴しましたが、そうもいかないように思います。そもそもの発端だったheader関数のエラーはE_WARNINGです。ヘッダを送信しようとしてできなかったという事象は「WARNING」という語感とは裏腹な、かなり深刻なものだと思います。E_WARNINGより重いエラーであるE_ERRORは「重大な実行時エラー。きないエラーを示します。スクリプトの実行は中断されます。」(マニュアル)とあるように、捕捉する前に終了してしまいます(実験で確認しました)。いうことですので、色々工夫の余地はあるとは思いますが、E_WARNINGレベルのエラーは捕捉するべきだと思います。