Warnings to Exceptions

Converting Warnings and Notices into Exceptions

The most useful handler throws an ErrorException, whose getSeverity() keeps the original level. A missing file then stops the code path, runs finally blocks and reaches the same catch and logging as any other failure. Laravel 2,157 and Symfony 6,093 install such a handler at startup (Laravel).

An error handler that throws ErrorException but respects @ and the maskPHP
<?php
set_error_handler(function (int $no, string $msg, string $file, int $line): bool {
    if (!(error_reporting() & $no)) return false;   // silenced by @ or masked out
    throw new ErrorException($msg, 0, $no, $file, $line);
});
try {
    $csv = file_get_contents('prices.csv');
} catch (ErrorException $e) {
    echo $e::class, " (severity {$e->getSeverity()}): {$e->getMessage()}\n";
}
var_dump(@file_get_contents('prices.csv'));    // @ still means "return false quietly"
Output
ErrorException (severity 2): file_get_contents(prices.csv): Failed to open stream: No such
  file or directory
bool(false)

Inside @, error_reporting() returns 4437, the fatal levels only, so the handler steps aside; without that test every @ in your libraries would throw. Convert E_DEPRECATED in tests, never in production, or a PHP upgrade becomes an outage.