久しぶりに他人が実装したphpコードを改修する機会があり、改めてphpのエラーレポートレベルに関して思うところがありました。
コードがあったほうが話がわかりやすいと思いますので用意しましょう。
はい。例えば、下記のようなコードが合ったとしましょう
fetchに関しては適当なレコードが連想配列で返却されるとイメージしてください。
<?php ini_set('display_errors', 'On'); error_reporting(E_ALL); class Car { public $engine; public $wheel; public static function apply($record) { $car = new Car(); $car->engine = $record['engine']; $car->wheel = $record['wheel']; return $car; } } $carRecord = $pdo->fetch(PDO::FETCH_ASSOC); $car = Car::apply($carRecord);
これは問題なく動きます。
ところが開発途中でRDBのテーブルの属性名がイケてないなと思い wheel という属性名を wheels と複数形にしたとします。
ソースコードに関しては変更するのを忘れてしまいました。
だとしても当然スクリプト言語ですから動きます。これは。そういう設計ですから。
Notice errorを表示する設定の場合は、下記のようなエラーを吐いてくれます。
Notice: Undefined index: wheel in hoge.php on line 12
これは文字通り連想配列に存在しないインデックスにアクセスしているというエラーなのですが、エラーレベルってNoticeなんですよね。
これもうアプリケーション動かないじゃないですか。
しばらくコンパイラ言語で開発していると少々このギャップに戸惑ったという話。
さらに公式によると error_reporting の初期値は E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED なんですよね。
初期値にNoticeが含まれていないんですよね。
これがまた学習レベルの浅いphpユーザがなんたるかと言われることにつながっているような気がしなくもないです。
開発中はできればNoticeエラーをonにすることで、Noticeエラーは積極的に潰していきましょう。
さらに別の側面から見るために下記のようなコードを用意しました。
<?php ini_set('display_errors', 'On'); error_reporting(E_ALL); class Car { public $engine; public $wheel; public static function apply($record) { $car = new Car(); $car->engine = $record['engine']; $car->wheel = $record['wheel']; return $car; } } $car = new Car(); $car->status = "stop";
phpは未定義のメンバ変数を動的に追加できます。
つまり上記のコードはエラーでもなんでもなくphpでは正しいコードなのです。そういう設計ですから。
これもなかなかしんどいですよ。例えば意図的ではなくタイポなどが原因だったらバグですから。
こういった事象をUTなどでカバーするっていうのは、なんかちょっと無駄なような気がしますし、できたとしてもそれに追従するコストが結構かかります。
ようするに無駄なコストをかけざるをえないんじゃないかと思います。
コンパイラ言語などでコンパイル時に検出できるたぐいの不具合であれば、そちらを使うに越したことはないじゃないか。という結論。
[…] 改めてphpのerror_reportingは心もとないなと感じた 実行時設定 – php.net error_reporting – php.net […]