PHP 7以降では、PHPのエラーは基本的にErrorクラスとして扱われ、try-catchブロックで捕まえることができるようになりました。(Catchable Fatal Error)
ちなみにPHP 7では下記の2つのクラスがThrowableクラスを継承しており、両方捕まえるときは、try-catchブロックでThrowableをcatchするように書けばOKです。
- Exception
- Error
ただし、一部のFatal Error(例: Memory Exhausted Error)はtry-catchブロックで捕まえることができません。
Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 9792 bytes) in ....
この場合は、register_shutdown_functionを使って、PHPのプログラムが終了したときにエラー処理をするしかなさそうです。
register_shutdown_functionとerror_get_lastを使ってエラー処理をする関数のコード例を示します。
<?php
// PHPのError定数 => 文字列表現の連想配列
const ERROR_CODE_TO_STRING = [
E_ERROR => 'E_ERROR',
E_WARNING => 'E_WARNING',
E_PARSE => 'E_PARSE',
E_NOTICE => 'E_NOTICE',
E_CORE_ERROR => 'E_CORE_ERROR',
E_CORE_WARNING => 'E_CORE_WARNING',
E_COMPILE_WARNING => 'E_COMPILE_WARNING',
E_USER_ERROR => 'E_USER_ERROR',
E_USER_WARNING => 'E_USER_WARNING',
E_USER_NOTICE => 'E_USER_NOTICE',
E_STRICT => 'E_STRICT',
E_RECOVERABLE_ERROR => 'E_RECOVERABLE_ERROR',
E_DEPRECATED => 'E_DEPRECATED',
E_USER_DEPRECATED => 'E_USER_DEPRECATED',
];
// $catchLevelにキャッチしたいエラーレベルの定数を渡します。
// 需要があるかわかりませんが、bit演算の&を使って捕まえるべきか判定しているので、
// E_ALLを渡すとE_NOTICEエラーも捕まえられます。
function catchError($catchLevel)
{
register_shutdown_function(function() use($catchLevel){
$error = error_get_last();
if(empty($error))
{
return;
}
$shouldCatch = $error['type'] & $catchLevel;
if($shouldCatch)
{
$error['typeString'] = ERROR_CODE_TO_STRING[$error['type']] ?? '';
// $error containus type message, file, line information.
// do something nice...
echo json_encode($error, JSON_PRETTY_PRINT);
// ここでメモリを大量に消費するような処理を書くと再度、Memory Exhausted Errorになってしまうので注意。
// とはいえ、memory_limitの設定容量が十分あり、常識的な処理であれば、
// エラー部分の処理でメモリ不足を心配する必要はありません。
}
});
}
コメント