SlideShare a Scribd company logo
90分間濃縮
PHPエラーの教室

  Shimokita.php / Yusuke Ando (@yando)
Shimokita.php / Yusuke Ando (@yando)
福岡でのボランティア急募!
  Shimokita.php / Yusuke Ando (@yando)
こんな経験はありませんか?




  Shimokita.php / Yusuke Ando (@yando)
画面が真っ白に

Shimokita.php / Yusuke Ando (@yando)
画面にお経みたいなものがでる

   Shimokita.php / Yusuke Ando (@yando)
サーバのログがゴミ溜めになっている

    Shimokita.php / Yusuke Ando (@yando)
エラー正しく扱えていますか?




  Shimokita.php / Yusuke Ando (@yando)
Shimokita.php / Yusuke Ando (@yando)
Shimokita.php / Yusuke Ando (@yando)
PHPのエラーと例外に関する
取り扱い方法を見ていきます



  Shimokita.php / Yusuke Ando (@yando)
エラーのイロハ

•何故エラーが起きるのか
•エラー関連の設定
•エラーハンドリング
•例外処理

     地味だけれど重要な知識


   Shimokita.php / Yusuke Ando (@yando)
何故エラーが起きるのか



 Shimokita.php / Yusuke Ando (@yando)
エラーとは

•PHPのスクリプトを実行する際の各段階で発生
•構文解析時の問題
•処理の実行中に発生する問題
•拡張モジュールなどの外部プログラム内
•ネットワーク処理など通信が発生した場合


   状況に応じて正しい対処が異なる


     Shimokita.php / Yusuke Ando (@yando)
エラーの種類
       種類                           内容

  E_ERROR / Fatal        実行不可能:処理は停止、白画面

E_WARNING / Warning    警告:実行時に問題発生、処理は継続

  E_PARSE / Parse      解析不能:処理は始まらない、白画面

 E_NOTICE / Notice    通知:問題になりうる状況、処理は継続

    E_STRICT /
                       バージョン間の互換性に関するエラー
  E_DEPRECATED


        重大度に応じてレベルが存在
          Shimokita.php / Yusuke Ando (@yando)
FATAL /                        NOTICE /
  PARSE                        WARNING etc

何も出ないか、壊れた画面かの分かれ目
    Shimokita.php / Yusuke Ando (@yando)
E_PARSE / Parse
        echo echo;


        echo date()
        echo time()




•トークンの出現位置が不正
•セミコロン忘れ、ブレースの対応関係
•全角スペース混入

      シンプルな構文エラー
    Shimokita.php / Yusuke Ando (@yando)
E_ERROR / FATAL
        $obj = 1;
        if ($obj === null) {
          $obj = getObject();
        }
        $obj->myFunc();



•構文は合っていたが、実行しようとした処理が失敗
•関数名間違い、オブジェクトの取り違い
•外部モジュールのエラー

 コードが実行された時の状態が問題
    Shimokita.php / Yusuke Ando (@yando)
E_WARNING

     $body = file_get_contents( hoge.txt );
     echo Hello ;




•処理は実行できたが、失敗してしまった場合
•ファイルやネットワークの処理など
•正常に処理を継続する事はおそらく難しい

エラーを検知してふさわしい処理が必要
    Shimokita.php / Yusuke Ando (@yando)
E_NOTICE
     if ($data == null) {
       echo Hello ;
       echo HOGE;
     }




•未定義の変数、定数を使った場合
•関数への引数が正しくない
•考慮の足りないコードで発生しやすい

   動いていたとしても危険性あり
    Shimokita.php / Yusuke Ando (@yando)
E_STRICT / E_DEPRECATED
      class Sample
      {
         function foo()
         {
            echo "Hi";
         }
      }
      Sample::foo();



•PHP4の文法をPHP5で利用した場合
•将来廃止される予定の機能を使った場合

古い遺産で発生しやすく、不可避な場合も
     Shimokita.php / Yusuke Ando (@yando)
Segmentation Fault




•ログには Segmentation Fault とだけ記録される
 サーバのアップデートなどが必要になる
       Shimokita.php / Yusuke Ando (@yando)
エラー関連の設定



Shimokita.php / Yusuke Ando (@yando)
エラーが画面に出ない?

•発生したエラーを表示するかは設定次第
•php.ini または htaccessなどの設定
•実行時に設定を強制的に変更する事も可能
•ini_set() error_reporting() display_errors()
•エラーをログに記録するかどうかは別の設定


   開発時は表示、運用時は記録が正しい


           Shimokita.php / Yusuke Ando (@yando)
正しい設定
error_reporting = E_ALL
display_errors = On
display_startup_errors = On        全てを検知、表示
log_errors = On
error_log = /path/to/error.log



error_reporting = E_ALL & E_DEPRECATED & E_STRICT
display_errors = Off
display_startup_errors = Off
log_errors = On
                                   互換性エラーは無視
error_log = /path/to/error.log


                                       表示はしない

            Shimokita.php / Yusuke Ando (@yando)
運用中のエラーを隠す理由

DB情報などが入る場合も

                    不具合の発生時に警
                      告が出る場合


 表示が崩れるかも




 Shimokita.php / Yusuke Ando (@yando)
こういうのは...




Shimokita.php / Yusuke Ando (@yando)
これもダメ

   <?php
   @trigger_error("Hi");
   echo "World";

                              強制的に無視




これを多用すると障害発生時に手がかり0


     Shimokita.php / Yusuke Ando (@yando)
エラーハンドリング



Shimokita.php / Yusuke Ando (@yando)
エラーハンドリング

•エラーが発生した後に行う処理
•発生したエラーのレベルに応じて処理が可能
•標準のエラーハンドラはphp.iniの設定に応じた処理
•任意の処理を登録する事も可能
•エラーハンドラから元の処理にも戻れる
•任意のエラーを起こす事も可能

 フレームワークなどでも利用されている


      Shimokita.php / Yusuke Ando (@yando)
エラーハンドリングの例
      function handler($no, $str){
        echo "Error $strn";
        return true;
      }


      set_error_handler('handler');
      echo $a;
      trigger_error('My Error');



•エラーの情報を引数で受け取る
•returnで元の場所へ復帰する

    標準の処理以外の対応が可能
     Shimokita.php / Yusuke Ando (@yando)
エラーハンドリングの例2




 Shimokita.php / Yusuke Ando (@yando)
エラーハンドリングの後
        $body = file_get_contents( hoge.txt );
        if ($body === false) {
            my_error();
            exit;
        }
        echo Hello ;



•処理が継続するWarningやNoticeの後には適切な処理
•不足すると空っぽのリスト、崩れた画面などに繋がる

  ハードな運用を耐えているかの試金石
       Shimokita.php / Yusuke Ando (@yando)
重要なんです!




さすがPHP、エラー時の返り値がバラバ(ry

    Shimokita.php / Yusuke Ando (@yando)
例外処理



Shimokita.php / Yusuke Ando (@yando)
例外処理

•PHP5から利用できるエラー処理
•Javaなどの言語でも実績がある機構
•誤った利用方法により有害無益になっている例多数
•正しく使えばエラー処理がすごく楽になる
•間違って使うと無駄にコードが多くなって、挙動も崩壊


   これからは例外を使って行きたい


     Shimokita.php / Yusuke Ando (@yando)
例外処理の例
      function hoge()
      {
         if (true) {
             throw new Exception('Error!');
         }
      }
      try {
         hoge();
      } catch (Exception $e) {
         echo $e->getMessage();
         exit;
      }



例外オブジェクトをthrowするとcatchに入る
     Shimokita.php / Yusuke Ando (@yando)
例外オブジェクト
•オブジェクトからエラー情報が取得可能
•Exceptionをnewする時にセットされた情報を取得
•getMessage getCode getFile getLine getTrace




          Shimokita.php / Yusuke Ando (@yando)
例外処理の失敗例
 function hoge()
 {
    if (true) {
        return new Exception('Error!');
    }
 }
 try {
    hoge();
 } catch (Exception $e) {
    echo $e->getMessage();
    exit;
 }



例外オブジェクトをreturn...
Shimokita.php / Yusuke Ando (@yando)
例外処理の失敗例2
   function hoge()
   {
      if (true) {
          throw new Exception('Error!');
      }
   }
   try {
      hoge();
   } catch (Excepton $e) {
      echo $e->getMessage();
      exit;
   }



catchする例外の型が合っていない
  Shimokita.php / Yusuke Ando (@yando)
例外処理の失敗例3
  function hoge()
  {
     if (true) {
         throw new Exception('Error!');
     }
  }
  try {
     hoge();
  } catch (Exception $e) {


  }




catchしてもなにもしていない...
 Shimokita.php / Yusuke Ando (@yando)
例外処理に関する誤解

•try catchをたくさん書くのが正しいコード
→きちんと書けば巨大なコードでもcatchは一箇所でよい
•入力エラーなどでも例外処理を使うべき
→通常発生しうるものは例外ではない
•catchすればとりあえずはOK
→catchするのはどうしても必要な場合のみ


 正しく例外を扱うプロジェクトの稀な事

       Shimokita.php / Yusuke Ando (@yando)
例外処理の自動化


       function handler($exception) {
          echo $exception->getMessage();
       }
       set_exception_handler( handler );




•catchされなかった例外が最終的に指定した関数へ到達




      Shimokita.php / Yusuke Ando (@yando)
まとめ

•「画面が白くなりました」は無意味
•エラーの内容を確認しなければ対応は不可能
•Noticeが多いからエラーを消すは本末転倒
•通常稼働中はエラーが発生しないのが理想
•ライブラリやプラグインがNoticeやWarningを垂れ流すの
は非常に害が大きく、廃れる原因

     no more error_reporting(0);
         no more @hoge();
      Shimokita.php / Yusuke Ando (@yando)
質問?




Shimokita.php / Yusuke Ando (@yando)

More Related Content

90分間濃縮 PHPエラーの教室