この「小さな」記事は、
この記事で取り上げたトピックを発展させたものです。
ご存知のように、PHPはかなり前に生まれたものであり、その場合でも、発生したエラーをどう処理するかという疑問が生じました。 PHPの疑いのない先駆者であるPerlには、デフォルトでエラー処理システムがありませんでした。 エラーが発生した場合、サーバーは500番目のエラーをスローし、それだけでした。 したがって、警告、致命的なエラー、および通知は、プログラマーのすでに困難な作業を容易にするための真のブレークスルーでした。 しかし、時間が経っても、PHPのメカニズムは変わらず、ご存知のようにテクノロジーは止まるのを好みません。
そして今、PHP 5.0では、最終的に、プログラマの武器庫に、例外や例外などの強力なツールがありました。 例外には多くの利点がありますが、ごく一部を説明します(不正確または読み書きができない場合もありますが、「自分の言葉で」説明されているため、利点を説明する科学用語を探すのが面倒でした)。
- エンドツーエンドの生成。 これは、コード内のどこかで例外が発生すると、メインスクリプトの制御構造と関数から最初のcatchブロックまたはメイン関数(ストリーム内の対応するエラー)への連続的な出口が発生することを意味します。
- 継承を通じてコア例外クラスをオーバーライドする機能
- 複数のタイプの例外を同時に処理する機能
標準のPHPエラーを処理する可能性は非常に限られています。
- @でブロックできます
- set_error_handlerを使用してハンドラーを設定できます
- trigger_errorで独自のエラーを生成できます
標準エラー処理メカニズムは時代遅れであり、互換性の理由でのみ言語に存在することは明らかです。
この短い記事では、例外メカニズムを使用するように変換することで、普遍的なエラー処理がどのように行われるかを強調します。
主なアイデア:ハンドラーを標準エラー用に配置し、例外をスローします:
- <?php
- クラス MyException extends Exception {
- public function __construct($ message、$ errorLevel = 0、$ errorFile = '' 、$ errorLine = 0){
- 親:: __コンストラクト($メッセージ、$エラーレベル);
- $ this-> file = $ errorFile;
- $ this-> line = $ errorLine;
- }
- }
- set_error_handler ( create_function ( '$ c、$ m、$ f、$ l' 、 'throw new MyException($ m、$ c、$ f、$ l);' )、E_ALL);
- ?>
*このソースコードは、 ソースコードハイライターで強調表示されました。
このコードは、別のファイルに取り出して、一度だけ接続する必要があります。 MyExceptionクラスは、コンストラクターに2つの追加パラメーター(ファイルとエラーのある行番号)を追加することにより、標準のExceptionクラスを拡張します。
set_error_handler関数は、動的に作成されたラムダ関数(コールバック)をエラーハンドラーとして設定し、エラーが発生すると例外をスローします。 特に、set_error_handler関数の2番目のパラメーターに注意してください。 このパラメーターは、ユーザー定義(つまり、私たちの)ハンドラーがどのタイプのエラーに対して呼び出され、どのエラーに対して標準のハンドラーが呼び出されるかを決定するため、非常に重要です。 この例では、値をE_ALLに設定します。これは、すべてのタイプのエラーに対してハンドラーが呼び出されることを意味します。
通知などのいくつかのタイプのエラーを処理したくない場合は、簡単にこれを示すことができます。
set_error_handler ( create_function ( '$ c、$ m、$ f、$ l' 、 'throw new MyException($ m、$ c、$ f、$ l);' )、E_ALL&〜E_NOTICE); *このソースコードは、 ソースコードハイライターで強調表示されました。
しかし、私にとっては理想的なアプローチは、すべてのエラーを処理することですが、一部のタイプ、特に通知では、例外をスローせず、画面に情報を表示することをお勧めします。
set_error_handler ( create_function ( '$ c、$ m、$ f、$ l' 、 'if($ c === E_NOTICE){echo'これは注意: '。$ m} else {throw new MyException($ m、$ c、$ f、$ l);} ' )、E_ALL); *このソースコードは、 ソースコードハイライターで強調表示されました。
人生に近い例を考えてみましょう。 チャレンジ:
サイトには登録フォームがあります。例外を利用して、検証エラーの処理とユーザーに対する適切な警告の発行を実装する必要があります。
実際には2つの困難があります。
- 一度に1つではなく、すべてのエラーを一度に印刷します
- 検証エラーの処理を他の例外の処理から分離する
解決策:
ここでの主な難点は、例外の非常に悪名高い利点です。これは、例外をスローすると、制御構造が最初のcatchブロック(またはスクリプトの最後)で終了することです。 この落とし穴を回避するため、新しい累積クラスFormFieldsListExceptionを定義します。このクラスでは、エラー蓄積メカニズムを実装し、すべてのフィールドが検証された後にのみ例外をスローします。 クラスFormFieldsListExceptionで、データを格納する保護されたメンバー$ _listを定義します。 $ _list配列の操作を簡素化するために、クラスが2つのインターフェイスを実装することを示します。配列の要素にアクセスするためのArrayAccessと、ループで作業するためのIteratorです。 検証検証メソッドを初期化するときは、FormFieldsListExceptionオブジェクトを作成し、エラーが検出されたら、それらを通常の配列のようにFormFieldsListExceptionオブジェクトに追加します。
- <?php
- クラス FormFieldsListExceptionは例外を実装しますArrayAccess、Iterator {
- protected $ _list = array();
- パブリック 関数 __construct(){
- }
- パブリック 関数 offsetExists($インデックス){
- return isset($ this-> _ list [$ index]);
- }
- パブリック 関数 offsetGet($インデックス){
- return $ this-> _ list [$ index];
- }
- パブリック 関数 offsetSet($インデックス、$値){
- if (isset($ index)){
- $ this-> _ list [$ index] = $ value;
- }
- その他 {
- $ this-> _ list [] = $ value;
- }
- }
- パブリック 関数 offsetUnset($インデックス){
- 設定解除($ this-> _ list [$ index]);
- }
- パブリック 関数 current(){
- 現在の値を返す ($ this-> _ list);
- }
- パブリック ファンクションキー(){
- リターンキー($ this-> _ list);
- }
- パブリック 関数 next(){
- 次を返す ($ this-> _ list);
- }
- public function rewind(){
- return reset($ this-> _ list);
- }
- public function valid(){
- return ( bool )$ this- > current();
- }
- }
- ?>
*このソースコードは、 ソースコードハイライターで強調表示されました。
検証手順が完了したら、エラーメッセージが入力されているかどうかを確認します。 その場合、準備された例外オブジェクトを「スロー」します。
例外をキャッチするには、2つのcatchブロックを使用します:FormFieldsListExceptionと他のすべての例外用です。 これにより、さまざまなタイプの例外が発生したときに、さまざまなタイプのアクションを指定できます。
- <?php
- 関数 validateForm(){
- $ e = new FormFieldsListException();
- if ($ errorInFirstField){
- $ e [] = '最初のフィールドのエラー' ;
- }
- if ($ errorInSecondField){
- $ e [] = '2番目のフィールドのエラー' ;
- }
- if (( bool )$ e-> current()){
- $ eを投げます。
- }
- }
- {
- validateForm();
- }
- catch (FormFieldsListException $ error){
- echo '<b>フィールドのエラー</ b>:<br />' ;
- foreach ($エラーは $ e として ){
- エコー$ e。 '<br />' ;
- }
- }
- catch (例外$エラー){
- echo '検証エラーではありません! ' 。$ error-> getMessage();
- }
- ?>
*このソースコードは、 ソースコードハイライターで強調表示されました。
ここにある! :)
適切に設計された例外システムは、特にMVCパターンを使用してアプリケーションを開発する場合に、プログラマの生活を大幅に簡素化できます。 この小さな研究が示したように、PHP5の例外処理システムには、特定の状況での近代化と使用のためのかなりの準備が含まれています。
PS :この記事で紹介したプログラマーの中には、例外を使用してフォームを検証することを検討しており、最適な選択肢ではありません(ちなみに、「件名に含まれる」読者にこれについてコメントするようお願いします)、この例を検討するようお願いします単なるケーススタディであり、行動のガイドではありません。
PPS :
ashofthedreamの同志に感謝し
ます 。この紛争により、例外をより詳細に研究するようになりました。
UPD :
PHPブログに移動しました