Причины неработающего PHP и способы их устранения

Раздел: Программирование на PHP -> Отладка и ошибки

Основные причины и решения

Самое эффективное решение - включить отображение всех ошибок PHP на этапе разработки.

По умолчанию PHP скрывает многие ошибки, особенно на production-серверах. Для отладки необходимо принудительно включить вывод ошибок в коде или конфигурации.

Вставьте в начало скрипта (или в общий файл конфигурации) следующий код:

<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
?>

Эти три строки гарантируют, что PHP будет показывать все ошибки, включая фатальные и предупреждения.

Если ошибки всё равно не отображаются:

  • Проверьте, не переопределяются ли эти настройки в php.ini или .htaccess.
  • Убедитесь, что конфигурация не блокируется директивой display_errors = Off.
  • Обратите внимание на права доступа к файлам - PHP может не иметь права на запись логов.

Типичная ошибка: после включения отображения ошибок на экране всё равно пусто.

Причина - фатальная ошибка на этапе компиляции или парсинга (syntax error) до того, как была выполнена строка ini_set. В таком случае помогает просмотр логов веб-сервера (error_log) или запуск PHP через CLI с флагом -l.

Как проверить синтаксис PHP-файла без выполнения?

Используйте встроенную проверку синтаксиса из командной строки:

php -l index.php

Команда покажет наличие синтаксических ошибок (parse error) без запуска скрипта. Если ошибок нет, выводится No syntax errors detected.

Часто забывают, что синтаксическая ошибка может быть вызвана лишней запятой, неправильными скобками или не закрытым тегом ?>.

Какие логи сервера помогут найти причину?

Ошибки выполнения часто записываются в error_log веб-сервера (Apache/Nginx) или в журнал PHP. Чтобы узнать путь к логам, создайте файл:

<?php phpinfo(); ?>

Найдите строки error_log или syslog. В типичной настройке Apache это /var/log/apache2/error.log, для Nginx - /var/log/nginx/error.log.

Пример использования пользовательского лога:

<?php
function customError($errno, $errstr) {
    error_log("Error [$errno]: $errstr", 3, "/tmp/php_errors.log");
}
set_error_handler("customError");
?>

Если лог не создаётся - проверьте права на запись каталога, или используйте системный syslog (параметр 0).

Как отловить фатальные ошибки и исключения?

Используйте блок try-catch и специальный обработчик фатальных ошибок через register_shutdown_function:

<?php
function shutdownHandler() {
    $error = error_get_last();
    if ($error && ($error['type'] === E_ERROR || $error['type'] === E_PARSE)) {
        echo "Фатальная ошибка: {$error['message']} в {$error['file']} на строке {$error['line']}";
    }
}
register_shutdown_function('shutdownHandler');
?>

Для исключений (Exception) оберните подозрительный код в try-catch:

<?php
try {
    // код, который может выбросить исключение
    $result = 10 / 0;
} catch (DivisionByZeroError $e) {
    echo 'Поймано исключение: ' . $e->getMessage();
} catch (Throwable $t) {
    echo 'Неизвестная ошибка: ' . $t->getMessage();
}
?>

Не все ошибки PHP являются исключениями (например, уведомления предупреждения), поэтому комбинируйте с обработчиком ошибок.

Как проверить версию PHP и наличие расширений?

Создайте файл с <?php phpinfo(); ?> и откройте в браузере. Найдите разделы с версией, загруженными модулями (gd, mysqli, pdo, json и т.д.). Если нужное расширение отсутствует, установите его:

# Для Ubuntu/Debian
sudo apt-get install php-mysql php-curl php-xml php-mbstring
# Для проверки загруженных модулей через CLI
php -m

Версия PHP может не поддерживать некоторые функции (например, random_int() требует PHP 7.0). Всегда проверяйте документацию.

Как использовать var_dump и debug_backtrace для поиска логических ошибок?

Помещайте var_dump($variable); или print_r($variable); в подозрительные места. Для трассировки вызовов:

<?php
function a() { b(); }
function b() { debug_backtrace(); }
$trace = debug_backtrace();
print_r($trace);
?>

Результат покажет стек вызовов, файлы и строки.

Осторожно с var_dump больших массивов - может превысить лимит памяти. Используйте var_export или пишите в лог.

Что делать, если ошибка связана с сессиями или кодировкой?

Проверьте, что сессия стартована до любого вывода (и нет пробелов до <?php):

<?php
session_start();
// далее код
?>

Для кодировки убедитесь, что заголовки файла соответствуют:

<?php
header('Content-Type: text/html; charset=utf-8');
?>

Частая ошибка - сохранение файла в кодировке UTF-8 с BOM, что вызывает лишний вывод и нарушение работы session_start.

Как настроить Xdebug для пошаговой отладки?

Установите Xdebug (например, через pecl) и настройте в php.ini:

zend_extension=xdebug.so
xdebug.mode=debug
xdebug.start_with_request=yes
xdebug.client_host=127.0.0.1
xdebug.client_port=9003

Затем настройте IDE (PhpStorm, VSCode) на прослушивание соединений. После этого можно ставить точки останова и шагать по коду.

Если Xdebug не подключается, проверьте брандмауэр, порт 9003 и что PHP использует правильную версию расширения.

Расширенные примеры и команды для отладки PHP

Пример 1: Включение всех ошибок через .htaccess и php.ini

Добавьте в .htaccess (если AllowOverride включён):

Пример
php_flag display_errors On
php_flag display_startup_errors On
php_value error_reporting -1

Либо в php.ini (рекомендуется только для разработки):

Пример
display_errors = On
display_startup_errors = On
error_reporting = E_ALL

Результат:

Любая ошибка (Notice, Warning, Parse error) будет выводиться на экран.

Пример 2: Использование error_log для записи в файл

Пример
<?php
// Запись предупреждения в лог
error_log("Это сообщение в лог", 3, "/var/log/php_app.log");
// Другой способ - через trigger_error
trigger_error("Пользовательская ошибка", E_USER_WARNING);
?>

Лог-файл будет содержать временные метки и текст ошибки.

[17-Mar-2025 12:00:00 UTC] Это сообщение в лог
[17-Mar-2025 12:00:01 UTC] PHP Warning:  Пользовательская ошибка in /var/www/index.php on line 6

Пример 3: Полный обработчик ошибок и исключений

Пример
<?php
// Установка пользовательского обработчика ошибок
set_error_handler(function($severity, $message, $file, $line) {
    throw new ErrorException($message, 0, $severity, $file, $line);
});
// Установка обработчика для фатальных ошибок
register_shutdown_function(function() {
    $error = error_get_last();
    if ($error && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) {
        $msg = "Фатальная ошибка: {$error['message']} в {$error['file']}:{$error['line']}";
        error_log($msg);
        echo $msg;
    }
});
// Блок try-catch для перехвата исключений
try {
    // код с потенциальной ошибкой
    undefinedFunction(); // Вызовет ошибку
} catch (Error $e) {
    echo 'Поймана ошибка: ' . $e->getMessage();
}
?>

Результат выполнения (в зависимости от ситуации):

Поймана ошибка: Call to undefined function undefinedFunction()

Пример 4: Поиск утечки памяти с помощью memory_get_usage

Пример
<?php
function memoryDebug() {
    static $start = null;
    static $peak = 0;
    if ($start === null) $start = memory_get_usage();
    $now = memory_get_usage();
    $peak = max($peak, $now);
    error_log(sprintf("Текущее: %d, Пик: %d, Разница: %d", $now, $peak, $now - $start));
}
// Вызывать в местах, где возможна утечка
memoryDebug();
// ... большой массив
$data = range(1, 100000);
memoryDebug();
?>
[17-Mar-2025 12:01:00 UTC] Текущее: 409600, Пик: 409600, Разница: 0
[17-Mar-2025 12:01:01 UTC] Текущее: 2244608, Пик: 2244608, Разница: 1835008

Пример 5: Проверка наличия и версий расширений через CLI

Пример
# Список всех установленных модулей
php -m | sort
# Полная информация о конкретном модуле
php -r "print_r(gd_info());"
# Проверка доступности функции
php -r "echo function_exists('mysqli_connect') ? 'Да' : 'Нет';"
[PHP Modules]
bz2
calendar
Core
ctype
...
[Zend Modules]
Xdebug

Array
(
    [GD Version] => bundled (2.1.0 compatible)
    [FreeType Support] => 1
    ...
)

Да

Пример 6: Продвинутый debug_backtrace с фильтрацией

Пример
<?php
function trace(string $message = '') {
    $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5);
    foreach ($backtrace as $frame) {
        error_log(sprintf(
            "%s - %s:%d %s%s()",
            $message,
            $frame['file'] ?? 'unknown',
            $frame['line'] ?? 0,
            $frame['class'] ?? '',
            $frame['function'] ?? ''
        ));
    }
}
// Использование
trace('Вызов из index.php');
?>
[17-Mar-2025 12:02:00 UTC] Вызов из index.php - /var/www/index.php:12  trace()

Пример 7: Настройка Xdebug для профилирования

Пример
# В php.ini:
xdebug.mode=profile
xdebug.output_dir=/tmp/xdebug
xdebug.profiler_output_name=cachegrind.out.%t.%p

После выполнения скрипта в /tmp/xdebug появится файл, который можно открыть программой (например, KCachegrind или Qcachegrind) для анализа узких мест.

Файл: cachegrind.out.1742212920.12345 (бинарный)

Почему не работает PHP - comments

En
почему не работает php (php)