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

Preview:

Citation preview

Shimokita.php / Yusuke Ando (@yando)Shimokita.php / Yusuke Ando (@yando)

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

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)

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 / PARSE

NOTICE / 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_ALLdisplay_errors = Ondisplay_startup_errors = Onlog_errors = Onerror_log = /path/to/error.log

error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICTdisplay_errors = Offdisplay_startup_errors = Offlog_errors = Onerror_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 $str\n"; return true;}

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

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

Shimokita.php / Yusuke Ando (@yando)

エラーハンドリングの例2

Shimokita.php / Yusuke Ando (@yando)

エラーハンドリングの後

ハードな運用を耐えているかの試金石

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

$body = file_get_contents(‘hoge.txt’);if ($body === false) { my_error(); exit;}echo “Hello”;

Shimokita.php / Yusuke Ando (@yando)

重要なんです!

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

Shimokita.php / Yusuke Ando (@yando)

例外処理

Shimokita.php / Yusuke Ando (@yando)

例外処理

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

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

Shimokita.php / Yusuke Ando (@yando)

例外処理の例

例外オブジェクトをthrowするとcatchに入る

function hoge(){ if (true) { throw new Exception('Error!'); }}try { hoge();} catch (Exception $e) { echo $e->getMessage(); exit;}

Shimokita.php / Yusuke Ando (@yando)

例外オブジェクト•オブジェクトからエラー情報が取得可能•Exceptionをnewする時にセットされた情報を取得•getMessage getCode getFile getLine getTrace

Shimokita.php / Yusuke Ando (@yando)

例外処理の失敗例

例外オブジェクトをreturn...

function hoge(){ if (true) { return new Exception('Error!'); }}try { hoge();} catch (Exception $e) { echo $e->getMessage(); exit;}

Shimokita.php / Yusuke Ando (@yando)

例外処理の失敗例2

catchする例外の型が合っていない

function hoge(){ if (true) { throw new Exception('Error!'); }}try { hoge();} catch (Excepton $e) { echo $e->getMessage(); exit;}

Shimokita.php / Yusuke Ando (@yando)

例外処理の失敗例3

catchしてもなにもしていない...

function hoge(){ if (true) { throw new Exception('Error!'); }}try { hoge();} catch (Exception $e) {

}

Shimokita.php / Yusuke Ando (@yando)

例外処理に関する誤解

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

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

Shimokita.php / Yusuke Ando (@yando)

例外処理の自動化

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

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

Shimokita.php / Yusuke Ando (@yando)

まとめ

no more error_reporting(0);no more @hoge();

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

Shimokita.php / Yusuke Ando (@yando)

質問?

Recommended