Ошибки и отладка
Кроме исключений, которые выбрасывает ваш код, PHP сам сообщает о проблемах: обращение к несуществующей переменной, деление на ноль, опечатка в имени функции. Умение читать эти сообщения экономит часы поиска ошибок.
Виды сообщений
| Вид | Что означает | Программа продолжается |
|---|---|---|
| Notice, Deprecated | Замечание: возможная неточность, устаревшая возможность | Да |
| Warning | Предупреждение: что-то пошло не так | Да |
| Fatal error | Фатальная ошибка | Нет |
| Parse error | Синтаксическая ошибка в коде | Не запускается |
Предупреждение не останавливает программу, но почти всегда означает ошибку в логике. Игнорировать его нельзя.
Чтение сообщения
Сообщение называет причину, файл и номер строки:
Warning: Undefined variable $total in /var/www/cart.php on line 12Начинайте с указанной строки. Если с ней всё в порядке, смотрите выше: причина часто находится на несколько строк раньше.
Показ ошибок
При разработке ошибки выводят на экран, на рабочем сайте — пишут в журнал. Этим управляют настройки:
<?php
error_reporting(E_ALL);
ini_set('display_errors', '1');
echo 'Показываются все ошибки';На рабочем сервере display_errors выключают: сообщение об ошибке раскрывает посетителю пути к файлам и детали кода.
Журнал ошибок
Функция error_log() записывает сообщение в журнал сервера. Пользователь его не видит:
<?php
function divide(int $a, int $b): ?float
{
if ($b === 0) {
error_log('Попытка деления на ноль');
return null;
}
return $a / $b;
}
echo divide(10, 4); // 2.5Предупреждения как исключения
Предупреждение нельзя перехватить через try. Функция set_error_handler() позволяет превратить его в исключение — и обрабатывать все проблемы одним способом:
<?php
set_error_handler(function (int $level, string $message) {
throw new ErrorException($message);
});
try {
echo $undefined;
} catch (ErrorException $error) {
echo 'Перехвачено: ', $error->getMessage();
}Так поступают фреймворки: любое замечание останавливает выполнение и попадает в общий обработчик.
Отладка
Чтобы понять, что лежит в переменной, её выводят функцией var_dump() — она показывает и тип, и значение:
<?php
$user = ['name' => 'Анна', 'age' => 25, 'active' => true];
var_dump($user['age']);
echo json_encode($user, JSON_UNESCAPED_UNICODE);Для больших массивов удобнее print_r() или json_encode(). В серьёзных проектах используют отладчик Xdebug: он останавливает программу на нужной строке и показывает все переменные.
Общий обработчик исключений
set_exception_handler() задаёт функцию, которая получит любое непойманное исключение. В ней показывают посетителю вежливую страницу, а подробности пишут в журнал:
<?php
set_exception_handler(function (Throwable $error) {
echo 'Что-то пошло не так. Мы уже разбираемся.';
});
throw new RuntimeException('База данных недоступна');Частая ошибка
Оператор @ перед выражением подавляет сообщение об ошибке. Проблема при этом никуда не исчезает — вы просто перестаёте её видеть:
<?php
$config = ['theme' => 'dark'];
// Плохо: $size = @$config['size'];
$size = $config['size'] ?? 14;
echo $size; // 14Вместо подавления проверяйте данные: оператор ??, isset(), file_exists().