第20章 デバッグ
エラーレポートの理解
PHPにはエラーレベルを設定する機能があります。初心者はこの概念を理解する必要があります。
// すべてのエラーを報告する
error_reporting(E_ALL);
// 注意: このコードには未定義の変数があるのでエラーが出力されます
echo $undefined_variable;
PHPのエラーレベルは下記になります。
値 | 定数 | 意味 |
---|---|---|
1 | E_ERROR | 重大な実行時エラー。スクリプトは中断します。 |
2 | E_WARNING | 実行時の警告。スクリプトは中断しません。 |
4 | E_PARSE | コンパイル時のパースエラー |
8 | E_NOTICE | 実行時の注意 |
16 | E_CORE_ERROR | PHPの初期始動時点での致命的なエラー |
32 | E_CORE_WARNING | 致命的ではない警告 |
64 | E_COMPILE_ERROR | コンパイル時の致命的なエラー |
128 | E_COMPILE_WARNING | コンパイル時の警告 |
256 | E_USER_ERROR | ユーザーによって発行されるエラーメッセージ。trigger_error()関数により発行 |
512 | E_USER_WARNING | ユーザーによって発行される警告メッセージ。trigger_error()関数により発行 |
1024 | E_USER_NOTICE | ユーザーによって発行される注意メッセージ。trigger_error()関数により発行 |
2048 | E_STRICT | 相互運用性や互換性を維持するためにコードの変更を提案 |
4096 | E_RECOVERABLE_ERROR | キャッチできる致命的なエラー |
8192 | E_DEPRECATED | 将来のバージョンで動作しなくなるコードについての警告 |
16384 | E_USER_DEPRECATED | ユーザー定義の警告メッセージ。trigger_error()関数により発行 |
64 | E_ALL | 全てのエラーと警告 |
開発環境ではE_ALLで全てのエラーを表示し、本番環境ではエラー表示はOFFにし、ログには全てのエラーを記録する事が推奨されています。
カスタムエラーハンドラの作成
エラーハンドリングにカスタム関数を使用する方法も重要です。例えばエラー発生時にslackやメールに送信するなど可能とします。
function customErrorHandler($errno, $errstr) {
echo "エラーが発生しました: [$errno] $errstr";
}
// カスタムエラーハンドラを設定
set_error_handler("customErrorHandler");
// エラーを発生させる
echo $undefined_variable;
全てのエラーレベルをハンドリングし、カスタム関数で条件分け
function specificErrorHandler($errno, $errstr, $errfile, $errline) {
if ($errno === E_NOTICE) {
echo "カスタム通知: $errstr\n";
return true; // このエラーは処理済み
}
return false; // その他のエラーは標準のエラーハンドラに渡す
}
set_error_handler("specificErrorHandler");
// 未定義の変数を参照する(E_NOTICEエラーを発生させる)
echo $undefinedVariable;
一箇所で全てのエラーハンドリングを管理できるが、全てのエラーがハンドラに渡されるため、処理が効率的でない
第二引数を使用して必要なエラーレベルだけ記述
function noticeErrorHandler($errno, $errstr, $errfile, $errline) {
echo "カスタム通知: $errstr\n";
}
// E_NOTICEレベルのエラーだけをハンドリング
set_error_handler("noticeErrorHandler", E_NOTICE);
// 未定義の変数を参照する(E_NOTICEエラーを発生させる)
echo $undefinedVariable;
// 0で割り算を行う(E_WARNINGエラーを発生させるが、このエラーハンドラでは処理されない)
$result = 10 / 0;
シンプルに記述でき処理も効率的だが、エラーレベル毎にカスタム関数を用意する必要がある
エラー処理のロジックが複雑で、各エラーレベルに対して異なる処理が必要な場合は、全てのエラーレベルをハンドリングして条件分けする方法が適しているかもしれません。
シンプルに特定のエラーレベルだけを処理したい場合、第二引数を使用した方法が効率的で可読性が高いでしょう。
デバッグツール
PHPのデバッグには、さまざまなツールとテクニックが利用できます。その中でもPHP自体に組み込まれた対話型のデバッグツールであるPHPDBGを紹介します。
PHPDBGの起動
phpdbgを起動するには、以下のコマンドを実行します。
phpdbg -q yourfile.php
一般的なコマンド
ブレークポイントの設定: 特定の行や関数でプログラムの実行を一時停止させることができます。
break filename.php:42 // 42行目でブレーク
break functionName // 関数が呼び出される時にブレーク
ステップ実行: 一行ずつコードを実行し、進行状況を確認することができます。
step // 次の行へ進む
continue // 次のブレークポイントへ進む
変数の値の確認: 実行中の変数の値を確認することができます。
print $variable // 変数の値を表示
実行制御: プログラムの実行を制御することができます。
run // プログラムを最初から実行
quit // phpdbgを終了
使用例
以下は、簡単なPHPスクリプトをphpdbgでデバッグする例です。
function sayHello($name) {
echo "Hello, " . $name . "!\n";
}
$name = "World";
sayHello($name);
このファイルをデバッグするために、以下のコマンドを実行します。
phpdbg -q example.php
デバッグセッションが開始されたら、ブレークポイントを設定して実行をコントロールすることができます。
break sayHello
run
これでsayHello関数が呼び出されるところで実行が一時停止します。
練習問題1.
以下のコードにはエラーが含まれています。何が問題なのかを特定し、どう修正すればよいかを考えてください。
function multiply($a, $b) {
return $a * $c;
}
echo multiply(5, 3);
練習問題2.
以下のコードが警告を発生させるとします。set_error_handler関数を使用して、カスタムエラーハンドラを作成し、この警告をキャッチして独自のエラーメッセージを表示するようにコードを修正してください。
$number = 0;
$result = 10 / $number;
echo $result;
練習問題3.
以下のコードにバグがあります。phpdbgを使ってデバッグを行い、バグを見つける手順を説明してください。
function calculate($a, $b) {
$result = $a - $b;
return $result * $result;
}
$result = calculate(3, 5);
echo "The result is: " . $result; // 期待する結果は4