新しい例外処理
非常に広く知られているところであるが、PHP5になって、オブジェクト指向プログラミングを行うための機能が大幅に強化された。
アクセス修飾子(public、protected、private)や__constructと__destruct、オブジェクトのCopy on Write実装など、変更点を挙げればきりがないが、その中でも重要な実装にもかかわらずノウハウの浸透が進んでいないものの1つに、例外処理の実装がある。
PHP4までは例外処理の実装が存在しなかったため、例外処理には独自のエラーフラグやPEAR_Errorなどを使用した実装が行われてきた。しかしこの方法は、ずっと以前からいわれているように、特殊な値のチェックなどへの対応が必要になったり、予想外の動作が起きた場合の対処に弱いなど、多くの煩雑な問題を抱えている。
PHP5からは、「try〜catch」ブロックと「Exception」オブジェクトを利用した例外処理がネイティブで実装され、上述のような旧来の例外処理が抱える問題を解決できるようになった。
この例外処理は非常に有用な仕組みなのだが、これまではPHP5を使っている開発現場でもなかなか浸透しづらい状態にあった。例外処理はライブラリを扱う際に特に有効になってくるのだが、多くのライブラリはPHP4とPHP5の両方で動作するように作成されていたため、PHP4では動作しないExceptionを組み込んでいないことが多かったからだ。
しかし、2007年末でPHP4のサポートが終了したことを受けて、PEARを筆頭とする多くの著名なライブラリの多くがPHP5対応を進めていく方針を表明している。今後はtry〜catchブロックを使った例外処理に対応したライブラリが一般化してくることだろう。
ここでは、このPHP5から導入された例外処理について、簡単にその挙動を見ていこう。
■基本的な使い方と継承によるcatch句の用法
PHPのExceptionクラスは、基本的に関数やメソッドの中で問題発生時にthrowして利用する。例外処理を含む関数/メソッドをtryブロック内で実行することで、例外が発生したときにcatchブロックに捕捉される。
<?php |
例外クラスとしては、Exceptionクラスを継承することで任意のクラスを定義することができ、これをcatch句のtype hintingで指定することで、例外の種類によって処理を分けることができる。
<?php |
catch句は複数設定可能で、スクリプトの上から順に判定されていく。また、ある例外クラスのサブクラスは、継承関係にある親クラスが指定されたcatch句にも捕捉される。
つまり上の例でいえば、発生した例外がTestExceptionであっても、Exceptionクラスを指定したcatch句にも捕捉されるということだ。そのため、catch句の順番をTestExceptionクラスとExceptionクラスとで逆にしてしまうと、例外TestExceptionは先に出てきたExceptionクラスが指定されたcatchブロックに捕捉されてしまい、TestExceptionを指定した2番目のcatchブロックは処理されなくなってしまう。
try { |
すべての例外クラスはExceptionクラスを継承しているので、catch句にExceptionクラスを指定すれば、発生してきた例外はすべて捕捉される。そのため、Exceptionクラスを指定したcatch句は、一番最後のブロックでなくてはならない。また同時に、よほど厳密にサブクラスのハンドリングを行わない限り、Exceptionクラスだけを抽出して補足することは困難であるともいえる。
実用性を考えた場合には、基底クラスのExceptionクラスを直接利用することはせずに、これを継承した任意の例外クラスを定義して、それをベースとして利用する方がよいだろう。
■例外の再throwとset_exception_handler
catch句で捕捉されなかったり、そもそもtryブロック外で実行された場合に発生した例外は、透過的に上位階層へ再throwされる。また、catchブロック内での明示的なthrowも可能なので、例外の処理を上位階層に渡してしまい、そちらで一括処理することが可能になる。
<?php |
上述のように、例外処理を上位階層に渡してしまう場合、最上位階層での例外処理を忘れずに実装しておかなくてはならない。処理の記述漏れなどで例外が最上位層でもキャッチされなかった場合には、Fetal Errorが発生し、処理が中断されてしまう。
そのような場合に備え、どこにも捕捉されなかった例外をハンドリングして処理する方法として、set_exception_handlerという関数が用意されている。この関数にcallback関数を設定しておくことで、めったに発生しない例外のキャッチ漏れなどに対処することができる。
<?php |
これによって、少なくともキャッチ漏れによるエラー終了は防ぐことができるが、この例外ハンドラによって例外がハンドリングされた場合でも、callback関数が実行し終えた段階で処理が中断してしまう。そのため、この関数はあくまでエラー終了という事態を防ぐための気休めと考えておいた方がいい。実用的には、callback関数の中で例外処理の漏れを報告するなどして、修正につなぐための情報を取得するようにしておくとよいだろう。
◆
今回はPHP5の例外処理の使用法に関して簡単に説明した。次回は、PHP5から実装されたSimpleXMLやPDOなどのモジュールについて解説していく予定である。
2/2 |
Index | |
例外処理の実装を把握する | |
Page1 PHP5を利用したこれからの開発に備える その前に……あなたはPHP5へ移行すべきか否か? |
|
Page2 新しい例外処理 基本的な使い方と継承によるcatch句の用法 例外の再throwとset_exception_handler |
PHP5で広がる! 開発環境 |
PHP関連記事 |
例外処理の実装を把握する PHP5で広がる! 開発環境(1) PHP4のサポートが終了し、いよいよPHP5への移行を視野に入れる時期が来た。PHP5の機能を生かした開発のポイントを紹介 |
|
クライアントPCに言語環境を入れる理由 Mac OS X+PHPでオールインワン環境(準備編) Webアプリ開発者に人気のMac OS X。効率的な開発のために複数バージョンのPHPを実行する環境を構築してみよう |
|
PHPに押し寄せるリスクと国際化の波 PHPカンファレンス2008レポート(前編) PHP4のサポートが完全に終了する。多くの新機能が投入されるPHP5.3へ移行か、国際化対応で開発が遅れるPHP6を待つか |
|
PHPによる大規模商用サービスの裏側 PHPカンファレンス2008レポート(中編) 企業のWebアプリケーション開発現場で利用されるPHP。開発現場の裏側にはさまざまなドラマが隠されている |
|
PHPユーザーは本当にほかの言語を知らないのか? PHPカンファレンス2008レポート(後編) PHPは本当にダメな言語なのだろうか。Perl、Ruby、Python、Java、JavaScriptの使い手が白熱した議論を行った |
|
- プログラムの実行はどのようにして行われるのか、Linuxカーネルのコードから探る (2017/7/20)
C言語の「Hello World!」プログラムで使われる、「printf()」「main()」関数の中身を、デバッガによる解析と逆アセンブル、ソースコード読解などのさまざまな側面から探る連載。最終回は、Linuxカーネルの中では、プログラムの起動時にはどのような処理が行われているのかを探る - エンジニアならC言語プログラムの終わりに呼び出されるexit()の中身分かってますよね? (2017/7/13)
C言語の「Hello World!」プログラムで使われる、「printf()」「main()」関数の中身を、デバッガによる解析と逆アセンブル、ソースコード読解などのさまざまな側面から探る連載。今回は、プログラムの終わりに呼び出されるexit()の中身を探る - VBAにおけるFileDialog操作の基本&ドライブの空き容量、ファイルのサイズやタイムスタンプの取得方法 (2017/7/10)
指定したドライブの空き容量、ファイルのタイムスタンプや属性を取得する方法、FileDialog/エクスプローラー操作の基本を紹介します - さらば残業! 面倒くさいエクセル業務を楽にする「Excel VBA」とは (2017/7/6)
日頃発生する“面倒くさい業務”。簡単なプログラミングで効率化できる可能性がある。本稿では、業務で使うことが多い「Microsoft Excel」で使えるVBAを紹介する。※ショートカットキー、アクセスキーの解説あり
|
|