У PHP є дві системи повідомлень про проблеми: винятки (throw) і помилки рушія - E_WARNING, E_NOTICE, E_DEPRECATED. Попередження за замовчуванням лише пишеться в лог, а виконання продовжується - часто з неправильними даними:
$content = file_get_contents('/missing.txt'); // Warning, $content === false
$data = json_decode($content); // працюємо далі з false
set_error_handler перехоплює такі помилки. Найпоширеніший прийом - перетворити їх на ErrorException:
set_error_handler(function (int $severity, string $message, string $file, int $line): bool {
if (! (error_reporting() & $severity)) {
return false; // помилку придушено через @ чи налаштування
}
throw new ErrorException($message, 0, $severity, $file, $line);
});
Тепер file_get_contents для неіснуючого файлу кидає виняток, і код не піде далі з false.
Laravel робить це за вас: обробник помилок фреймворку (HandleExceptions) перетворює попередження й notice на ErrorException. Тому в Laravel-застосунку «Undefined array key» - це виняток зі стек-трейсом, а не рядок у лозі. Застарілі (E_DEPRECATED) Laravel на винятки не перетворює, а пише в окремий канал логів, якщо його налаштовано (LOG_DEPRECATIONS_CHANNEL).
Що варто знати:
- Фатальні помилки (
E_ERROR, вичерпання пам'яті)set_error_handlerне перехоплює. Для них -register_shutdown_function()зerror_get_last(). - Оператор
@придушує попередження, але приховує й справжні проблеми. Краще перевіряти результат функції явно. - Сучасні функції часто вже кидають винятки:
json_decode(..., flags: JSON_THROW_ON_ERROR),random_int(), більшість методів класів SPL і intl.