Contents
6種類のエラーレベル
PHPは発生するエラーに応じてエラーレベルが決まっており、重要度の高い順に以下の6つが存在します。
- E_PARSE
- E_ERROR
- E_WARNING
- E_NOTICE
- E_DEPRECATED
- E_STRICT
それぞれのエラーレベルについて解説します。
E_PARSE
<?php
echo 'hoge';
echoo 'E_PARSE';
echo 'hoge';
/*
* 実行結果
*
* Parse error: syntax error, unexpected identifier "E_PARSE" in C:\xampp\htdocs\index.php on line 3
*/
E_PARSE は構文にミスがあった場合に発生します。このエラーはPHP実行環境がPHPファイルを読み込んだ時点で発生する為、PHPファイル内の処理は一切実行されません。
上記は「echo」が誤って「echoo」になっているので「Parse error」が発生しています。
注目すべきは「echoo」の前の正しい「echo」が出力されていない点です。先述したようにParse errorはPHPファイル読み込み時点で異常を検知するので処理は一切実行されません。
E_ERROR
<?php
echo 'hoge';
class hoge{}
class hoge{}
echo 'hoge';
/**
* 実行結果
*
* hoge
* Fatal error: Cannot declare class hoge, because the name is already in use in C:\xampp\htdocs\index.php on line 4
*/
E_ERRORは実行時の致命的なエラーで、メモリ確保に関する問題のように復帰できないエラーを示します。
上記はクラス「hoge」が二度定義されている為「Fatal error」が発生しています。
「Fatal error」は「Parse error」と違ってエラー発生箇所までの処理は行われます。その為クラス定義前の”hoge”は出力されています。ただしそれ以降の処理は実行されないので注意してください。
E_WARNING
<?php
echo 'hoge', '<br>';
echo "hoge$hoge", '<br>';
echo 'hoge', '<br>';
/*
* 実行結果
*
* hoge
*
* Warning: Undefined variable $hoge in C:\xampp\htdocs\index.php on line 3
* hoge
* hoge
*/
E_WARNINGは実行時の警告です。E_WORNINGは主に未定義の変数に対して発生しますが、引数の型を間違えたり、呼び出す引数の数を間違えた場合にも発生します。
E_WARNINGはその警告が発生した時点でその式の評価や文の実行が停止しますが、問題のない前後の処理は実行されます。
上記は定義していない「$hoge」をechoしようとした際に「Warning」が発生しています。
「式」の概念は少しややこしく、例えば「$hoge = 1」には3つの式があると解釈できます。つまり、変数$hogeで1つの式なので、上記の例でも$hogeだけがWorningの対象になっています。
しつこいようですが、E_WARNINGが停止するのは処理単体なので、$hogeを除いたecho文やその前後のecho処理は実行されます。
E_NOTICE
E_NOTICEはE_WARNINGより重要度の低い警告です。
<?php
$hoge;
echo $hoge;
$arr = ['item'=>'value'];
echo $arr[item];
/**
* 実行結果
* Warning: Undefined variable $hoge in C:\xampp\htdocs\index.php on line 3
*
* Fatal error: Uncaught Error: Undefined constant "item" in C:\xampp\htdocs\index.php:5 Stack trace: #0 {main} thrown in C:\xampp\htdocs\index.php on line 5
例えば上記のサンプルでは「代入されていない変数の使用」と「配列のキーが ‘ または ” で囲われていない」という問題があります。これらに対してはE_NOTICEが発生するとPHPマニュアルに記載されているのですが、現在だとE_WARNINGとE_ERRORになります。
異なるエラーが出力される原因はPHP8.0で多くのNoticeがWorningに変換されるようになった為です。こちらも詳細はPHPマニュアルを確認してみてください。
このようにPHPのバージョンによって出力されるエラーは異なるので、定期的にPHPマニュアルを確認する癖をつけるといいかと思います。
E_DEPRECATED
E_DEPRECATEDは過去に許されていた文法や関数が現行バージョンでは非推奨となっていたり、将来的に廃止されるものを使用していた場合に出力されるエラーです。現在ではあまり見かけるエラーではありません。
E_STRICT
E_STRICTは相互運用性や互換性維持のためにPHPがコード変更を提案する際に発生するエラーです。
E_STRICTはPHP5.4以降で実装されたものですが、PHP7.0で廃止され、今までE_STRICTとなっていたエラーは改めて別のレベルに移動になりました。詳細はPHPマニュアルを参照してください。
エラーの制御方法
例えば「E_PARSE」と「E_ERROR」以外は出力されないようにしたい、といった場合には「php.ini」の「error_reporting」を修正します。
私の環境では既定値は以下のようになっていました。
error_reporting=E_ALL & ~E_DEPRECATED & ~E_STRICT
error_reportingは15桁の2進数で表現されます。
これはE_ALL(111111111111111)に対してエラーコードの定数をビット演算子で否定(反転)したものをアンドして対象のE_ALLのビット位置を0にすることで「~を除く」を表現しています。
上記は「E_DEPRECATED」と「E_STRICT」を除いたエラーを出力するという意味になります。
全てのエラーを表現する方法
error_reportingで全てのエラーを指定する場合は「E_ALL」で正解ですが、書籍によっては「E_ALL | E_STRICT」と記載されているものがあります。
これはPHP5.4より前のバージョンだとE_ALLにE_STRICTが含まれていなかったという歴史的な問題で、PHP5.4以降であれば「E_ALL」で問題ありません。
エラーを表示するか否か
開発環境ではエラーをそのまま表示しても問題ありませんが、本番環境でエラーを表示するのはユーザビリティやセキュリティの観点からよくありません。
全てのエラーを非表示にするためにerror_reportingを全て0にする必要はありません。
php.iniにはerror_reporting以外に「display_errors」というオプションがあります。これをOffにすることで画面へのエラー出力を抑制できます。
本番環境ではdisplay_errorsをOffにしたうえで、画面ではなくログにエラーを出力する運用が一般的です。
その他のエラー定数について
本記事ではエラーは6種類しか紹介しませんでしたが、実際には以下の16種類のエラー定数が存在します。カッコ内は定数の値(int型)です。
- E_ERROR(1)
- E_WARNING(2)
- E_PARSE(4)
- E_NOTICE(8)
- E_CORE_ERROR(16)
- E_CORE_WARNING(32)
- E_COMPILE_ERROR(64)
- E_COMPILE_WARNING(128)
- E_USER_ERROR(256)
- E_USER_WARNING(512)
- E_USER_NOTICE(1024)
- E_STRICT(2048)
- E_RECOVERABLE_ERROR(4096)
- E_DEPRECATED(8192)
- E_USER_DEPRECATED(16384)
- E_ALL(32767)
※E_STRICTは廃止されましたが定数自体は残っています。
このようにPHPのエラーの種類は実はそこそこ多いですが、実際にはご紹介した6種類(実質的にはE_PARSE、E_ERROR、E_WARNINGの3種類)だけ覚えておけば問題ありません。エラー定数の詳細はPHPマニュアルを参照してください。
エラー制御演算子
最後にエラー制御演算子をご紹介します。
PHPには特定の式のエラーを強制的に抑制する演算子があります。それがエラー制御演算子「@」です。
<?php
echo @$hoge;
/**
* 実行結果
*
* (何も出力されない)
*/
上記の例のように未定義の変数を出力しようとすると通常はWarningとなりますが、@を付けるとエラーが出力されません。
ただし、このようにエラーを制御した方がよい場面というのは相当なレアケースかと思われます。エラー制御演算子の使用は避けた方がいいでしょう。