PHPの扱いづらいエラーをうまい感じにやるのとPHPerKaigi2019で登壇しますの話
今月末開催のPHPerKaigiがみえてきましたね!!
私もトークする予定です。
さて、
結構昔にPHPのエラーの話をかきまして、
これらもだいぶ古くなったなあ、ということで最近PHP7.3と一緒につかっているタレをかいておきますね。
こちらが最近のタレの様子です
<?php declare(strict_types=1); // defines define("START_MICRO_SEC", microtime(true)); // measure consume time. // error handling settings ini_set("display_errors", "0"); ini_set("display_startup_errors", "0"); ini_set('html_errors', "0"); error_reporting(E_ALL); // Noticeを含むすべてのエラーをキャッチしてExceptionに変換 set_error_handler(function ($severity, $message, $file, $line) { throw new ErrorException($message, 0, $severity, $file, $line); }); // FatalErrorなどリカバリできないエラーをキャッチ register_shutdown_function(function () { $error = error_get_last(); if (!is_array($error) || !($error['type'] & (E_ERROR | E_PARSE | E_CORE_ERROR | E_USER_ERROR | E_COMPILE_ERROR | E_RECOVERABLE_ERROR))) { // 処理時間ログ if (getenv('LOGGING_CONSUME_TIME') !== false) { $consume_ms = (microtime(true) - START_MICRO_SEC) * 1000; error_log("consume time: " . sprintf("%.2f ms", $consume_ms)); $memory = memory_get_peak_usage(false); error_log("consume memory: " . sprintf("%.2f kbyte", $memory / 1024)); } return; // 正常終了系 } // 異常終了系 // Logging un-excepted output buffer(debug|error messages) $something = ob_get_contents(); if (strlen($something) > 0) { error_log($something); } ob_end_clean(); // Error Logging error_log("Uncaught Fatal Error: {$error['type']}:{$error['message']} in {$error['file']}:{$error['line']}"); // response error if (!headers_sent()) { http_response_code(500); } echo "500 internal server error"; }); try { // enable output buffer ob_start(); // ここから require(__DIR__ . "/vendor/autoload.php"); echo "hello!"; // ここまでにアプリを書く ob_end_flush(); } catch (\Throwable $e) { // Uncaught Exception // Logging un-excepted output buffer(debug|error messages) $something = ob_get_contents(); if (strlen($something) > 0) { error_log($something); } ob_end_clean(); // Stack trace Logging $error_class_name = get_class($e); error_log("Uncaught Exception {$error_class_name}: {$e->getMessage()} in {$e->getFile()}:{$e->getLine()}\n{$e->getTraceAsString()}"); // response error if (!headers_sent()) { http_response_code(500); } echo "500 internal server error"; }
こう、非常に富豪なHelloworldですが、まあこれくらいやっておくとだいぶ便利(主観です)かなと思います。
Noticeも通らないですし、へんなログ出力もなくなります。
ただ、Output bufferをつかっているので、フレームワークによっては少々食い合わせに注意が必要です。
これにもうちょっと継ぎ足すならログ周りかなとおもいますが、クリティカルなエラーのあとだとライブラリのロガーは挙動が怪しい事があるので、標準装備のerror_log()を使うほうが良いかなと思います。あ、あとPsyshでシェルに落ちるとかも便利ですよね。
まあ、なにやってんのかわかんねえ!という方もいらっしゃるかと思いますが、大丈夫、こういうのは普通の人は自分でかきません、有名なフレームワークにまかせましょう!!
…といったような話をPHPerKaigiでできるといいなとおもいますので、ぜひ皆さんご参加ください!!
PHPerKaigi 2019 トークのご紹介です!
— PHPerKaigi 2022 @4/9-4/11 (@phperkaigi) 2019年3月6日
03/31 13:30〜 Track A 「帰ってきた!平成最後のオレオレフレームワークの作り方」 / うずらさん (@uzulla)
フレームワークの実装って中にいろんな設計パターンを含んでいて、とても面白いですよね。https://t.co/0S39zeF3af#phperkaigi
練馬で僕と握手!!!
こちらからは以上です。