Как получить полезные сообщения об ошибках в PHP?

Я нахожу программирование на PHP довольно разочаровывающим. Довольно часто я пытаюсь запустить скрипт и просто получить пустой экран обратно. Нет сообщения об ошибке, просто пустой экран. Причиной могла быть простая синтаксическая ошибка (неправильная скобка, пропущенная точка с запятой), сбой вызова функции или что-то еще полностью.

Очень сложно понять, что пошло не так. Я заканчиваю тем, что комментирую код, везде ввожу "эхо" и т. Д., Пытаясь сузить проблему. Но наверняка должен быть лучший путь, верно?

Итак, есть ли способ заставить PHP создавать полезное сообщение об ошибке, как это делает Java? Кто-нибудь может порекомендовать хорошие советы по отладке PHP, инструменты и методы?

33 ответа

Решение

Для синтаксических ошибок необходимо включить отображение ошибок в php.ini. По умолчанию они отключены, потому что вы не хотите, чтобы "клиент" видел сообщения об ошибках. Проверьте эту страницу в документации PHP для информации о 2 директивах: error_reporting а также display_errors, display_errors вероятно, тот, который вы хотите изменить. Если вы не можете изменить php.ini, вы также можете добавить следующие строки в файл.htaccess:

php_flag  display_errors        on
php_value error_reporting       2039

Вы можете рассмотреть возможность использования значения E_ALL (как упомянуто Gumbo) для вашей версии PHP для error_reporting чтобы получить все ошибки. больше информации

3 других пункта: (1) Вы можете проверить файл журнала ошибок, так как в нем будут все ошибки (если не было отключено ведение журнала). (2) Добавление следующих двух строк поможет вам отлаживать ошибки, которые не являются синтаксическими ошибками:

error_reporting(-1);
ini_set('display_errors', 'On');

(3) Другой вариант - использовать редактор, который проверяет ошибки при вводе, например, PhpEd. PhpEd также поставляется с отладчиком, который может предоставить более подробную информацию. (Отладчик PhpEd очень похож на xdebug и интегрируется непосредственно в редактор, поэтому вы используете одну программу для всего.)

Ссылка Картмана также очень хорошая: http://www.ibm.com/developerworks/library/os-debug/

Следующее включает все ошибки:

ini_set('display_startup_errors', 1);
ini_set('display_errors', 1);
error_reporting(-1);

Также смотрите следующие ссылки

Вы можете включить следующие строки в файл, который хотите отладить:

error_reporting(E_ALL);
ini_set('display_errors', '1');

Это переопределяет настройки по умолчанию в php.ini, которые просто заставляют PHP сообщать об ошибках в журнал.

Конфигурация PHP

2 записи в php.ini диктуют вывод ошибок:

  1. display_errors
  2. error_reporting

В производстве, display_errors обычно устанавливается на Off (Что хорошо, потому что отображение ошибок на производственных сайтах обычно нежелательно!).

Тем не менее, в процессе разработки, он должен быть установлен на On, так что ошибки отображаются. Проверьте!

error_reporting (начиная с PHP 5.3) по умолчанию E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED (имеется в виду все, кроме уведомлений, строгих стандартов и уведомлений об устаревании). Если вы сомневаетесь, установите его на E_ALL отобразить все ошибки. Проверьте!

ВОУ ВОУ! Нет проверки! Я не могу изменить свой php.ini!

Это позор. Обычно общие хосты не допускают изменения своего файла php.ini, и поэтому эта опция, к сожалению, недоступна. Но не бойся! У нас есть другие варианты!

Конфигурация времени выполнения

В желаемом скрипте мы можем изменять записи php.ini во время выполнения! Это означает, что он запустится, когда скрипт запустится! Милая!

 error_reporting(E_ALL);
 ini_set("display_errors", "On");

Эти две строки будут выполнять тот же эффект, что и изменение записей php.ini, как указано выше! Потрясающие!

Я все еще получаю пустую страницу /500 ошибок!

Это означает, что сценарий даже не запускался! Это обычно происходит, когда у вас есть синтаксическая ошибка!

С синтаксическими ошибками сценарий даже не попадает во время выполнения. Сбой во время компиляции, это означает, что он будет использовать значения в php.ini, которые, если вы не изменились, могут не допустить отображение ошибок.

Журналы ошибок

Кроме того, PHP по умолчанию регистрирует ошибки. На виртуальном хостинге он может находиться в отдельной папке или в той же папке, что и скрипт-нарушитель.

Если у вас есть доступ к php.ini, вы можете найти его под error_log запись.

Существует действительно полезное расширение под названием " xdebug", которое сделает ваши отчеты намного приятнее.

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

error_reporting(~0); ini_set('display_errors', 1);

быть помещенным в начало сценария, который находится под устранением неполадок. Это не идеально, идеальным вариантом является то, что вы также включаете это в php.ini и что вы регистрируете ошибки в PHP, чтобы поймать синтаксис и ошибки при запуске.

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

Следующие вещи для рассмотрения:

  • Установите Xdebug и включите удаленную отладку в вашей IDE.

Смотрите также:

Если вы супер крутой, вы можете попробовать:

$test_server = $_SERVER['SERVER_NAME'] == "127.0.0.1" || $_SERVER['SERVER_NAME'] == "localhost" || substr($_SERVER['SERVER_NAME'],0,3) == "192";

ini_set('display_errors',$test_server);
error_reporting(E_ALL|E_STRICT);

Это будет отображать только ошибки, когда вы работаете локально. Он также дает вам переменную test_server для использования в других местах, где это необходимо.

Любые ошибки, которые происходят до запуска скрипта, не будут обнаружены, но для 99% ошибок, которые я делаю, это не проблема.

В верхней части страницы выберите параметр

error_reporting(E_ERROR | E_WARNING | E_PARSE);

Чтобы сохранить это и сделать его совместимым, вы можете отредактировать файл php.ini. Обычно хранится в /etc/php.ini или же /etc/php/php.ini, но более местный php.iniможет перезаписать его, в зависимости от рекомендаций по настройке вашего хостинг-провайдера. Проверьте phpinfo() файл для Loaded Configuration File вверху, чтобы быть уверенным, какой из них будет загружен последним.

Ищите display_errors в этом файле. Должно быть только 3 экземпляра, из которых 2 прокомментированы.

Измените незакомментированную строку на:

display_errors = stdout
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', 1);
ini_set('html_errors', 1);

Кроме того, вы можете получить более подробную информацию с помощью xdebug.

Я рекомендую Nette Tracy для лучшей визуализации ошибок и исключений в PHP:

Нетт Трейси скриншот

Вы можете зарегистрировать свой собственный обработчик ошибок в PHP. Например, выгрузка всех ошибок в файл может помочь вам в этих непонятных случаях. Обратите внимание, что ваша функция будет вызываться независимо от того, на что установлена ​​ваша текущая error_reporting. Очень простой пример:

function dump_error_to_file($errno, $errstr) {
    file_put_contents('/tmp/php-errors', date('Y-m-d H:i:s - ') . $errstr, FILE_APPEND);
}
set_error_handler('dump_error_to_file');
error_reporting(E_ALL | E_STRICT);

И включить отображение ошибок в php.ini

Две ключевые строки, которые вам нужны, чтобы получить полезные ошибки из PHP:

ini_set('display_errors',1);
 error_reporting(E_ALL);

Как отмечают другие участники, они отключены по умолчанию из соображений безопасности. Полезный совет: когда вы настраиваете свой сайт, удобно переключаться между различными средами, чтобы эти ошибки были включены по умолчанию в вашей локальной среде и среде разработки. Это может быть достигнуто с помощью следующего кода (в идеале, в вашем index.php или конфигурационном файле, чтобы он был активен с самого начала):

switch($_SERVER['SERVER_NAME'])
{
    // local
    case 'yourdomain.dev':
    // dev
    case 'dev.yourdomain.com':
        ini_set('display_errors',1);
        error_reporting(E_ALL);
    break;
    //live
    case 'yourdomain.com':
        //...
    break;
}

Если вы пользователь Ubuntu, перейдите в свой терминал и выполните эту команду

sudo tail -50f /var/log/apache2/error.log

где будет отображаться последние 50 ошибок. Есть файл ошибки error.log для apache2, который регистрирует все ошибки.

Вы также можете попробовать PHPStorm в качестве редактора кода. Он найдет много PHP и других синтаксических ошибок, как вы печатаете в редакторе.

Попробуйте этот справочный инструмент отчетов об ошибках PHP. Это очень хорошая визуальная справка, которая помогла мне понять сложный механизм сообщения об ошибках.

FirePHP также может быть полезен.

В дополнение ко всем замечательным ответам здесь я хотел бы добавить специальное упоминание о библиотеках MySQLi и PDO.

Чтобы...

  1. Всегда видеть ошибки, связанные с базой данных, и
  2. Избегайте проверки типов возвращаемых данных для методов, чтобы увидеть, если что-то пошло не так

Лучший вариант - настроить библиотеки для выдачи исключений.

MySQLi

Добавьте это в верхней части вашего скрипта

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

Лучше всего перед использованием new mysqli() или же mysqli_connect(),

PDO

Установить PDO::ATTR_ERRMODE приписывать PDO::ERRMODE_EXCEPTION на вашем экземпляре соединения. Вы можете сделать это в конструкторе

$pdo = new PDO('driver:host=localhost;...', 'username', 'password', [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]);

или после создания

$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

Чтобы включить полный отчет об ошибках, добавьте это в ваш скрипт:

error_reporting(E_ALL);

Это приводит к появлению даже минимальных предупреждений. И на всякий случай:

ini_set('display_errors', '1');

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

"ОШИБКИ" - это самые полезные вещи для разработчиков, чтобы знать о своих ошибках и исправлять их, чтобы система работала идеально.

PHP предоставляет некоторые из лучших способов узнать разработчиков, почему и где их код получает ошибки, поэтому, зная эти ошибки, разработчики могут улучшить свой код разными способами.

Лучшие способы написать следующие две строки в верхней части скрипта, чтобы получить все сообщения об ошибках:

error_reporting(E_ALL);
ini_set("display_errors", 1);

Еще один способ использовать инструменты отладки, такие как xdebug, в вашей IDE.

Помимо параметра error_reporting и ini display_errors, вы можете получить ошибки SYNTAX из файлов журнала вашего веб-сервера. Когда я разрабатываю PHP, я загружаю логи веб-сервера моей системы разработки в мой редактор. Всякий раз, когда я тестирую страницу и получаю пустой экран, файл журнала устаревает, и мой редактор спрашивает, хочу ли я его перезагрузить. Когда я делаю, я прыгаю на дно, и есть синтаксическая ошибка. Например:

[Sun Apr 19 19:09:11 2009] [error] [client 127.0.0.1] PHP Parse error:  syntax error, unexpected T_ENCAPSED_AND_WHITESPACE, expecting T_STRING or T_VARIABLE or T_NUM_STRING in D:\\webroot\\test\\test.php on line 9

Этот ответ доведен до вас отделом резервирования.

  1. ini_set() / php.ini /.htaccess /.user.ini

    Настройки display_errors а также error_reporting были достаточно покрыты сейчас. Но просто напомнить, когда использовать какую опцию:

    • ini_set() а также error_reporting() применять только для ошибок во время выполнения.
    • php.ini должен быть в первую очередь отредактирован для установок разработки. (Web-сервер и CLI-версия часто имеют разные php.ini)
    • .htaccess флаги работают только для устаревших настроек (найдите нового хостера! Хорошо управляемые серверы дешевле.)
    • .user.ini являются частичными php.ini для современных установок (FCGI/FPM)

    И как грубая альтернатива для ошибок времени выполнения вы часто можете использовать:

    set_error_handler("var_dump");   // ignores error_reporting and `@` suppression
    
  2. error_get_last()

    Может использоваться для получения последнего уведомления о времени выполнения / предупреждения / ошибки, когда error_display отключен.

  3. $php_errormsg

    Суперлокальная переменная, которая также содержит последнее сообщение времени выполнения PHP.

  4. isset() Изыди!

    Я знаю, что это вызовет недовольство многих людей, но isset а также empty не должны использоваться новичками. Вы можете добавить подавление уведомления после того, как убедитесь, что ваш код работает. Но никогда раньше.

    Многие вопросы "что-то не работает", которые мы получаем в последнее время, являются результатом таких опечаток:

    if(isset($_POST['sumbit']))
    #                  ↑↑
    

    Вы не получите никаких полезных уведомлений, если ваш код усеян isset / empty / array_keys_exists, Иногда разумнее использовать @, поэтому уведомления и предупреждения идут в журналы как минимум.

  5. assert_options(ASSERT_ACTIVE|ASSERT_WARNING);

    Чтобы получить предупреждения для assert() разделы. (Довольно необычно, но более искусный код может содержать некоторые.)

    PHP7 требует zend.assertions=1 в php.ini также.

  6. declare(strict_types=1);

    Сгибание PHP в строго типизированный язык не исправит множество логических ошибок, но это определенно вариант для целей отладки.

  7. PDO / MySQLi

    И @Phil уже упоминал о параметрах сообщения об ошибках PDO / MySQLi. Подобные опции существуют и для других API баз данных.

  8. json_last_error() + json_last_error_msg

    Для анализа JSON.

  9. preg_last_error()

    Для регулярных выражений.

  10. CURLOPT_VERBOSE

    Чтобы отлаживать запросы curl, вам нужно как минимум CURLOPT_VERBOSE.

  11. shell/exec()

    Аналогично, выполнение команды оболочки не приведет к ошибкам само по себе. Тебе всегда нужно 2>&1 и посмотреть на $errno.

Вы можете включить полный отчет об ошибках (включая уведомления и строгие сообщения). Некоторые люди считают это слишком многословным, но это стоит попробовать. Задавать error_reporting в E_ALL | E_STRICT в вашем php.ini.

error_reporting = E_ALL | E_STRICT

E_STRICT уведомит вас об устаревших функциях и даст рекомендации о лучших методах выполнения определенных задач.

Если вы не хотите получать уведомления, но считаете полезными другие типы сообщений, попробуйте исключить уведомления:

error_reporting = (E_ALL | E_STRICT) & ~E_NOTICE

Также убедитесь, что display_errors включен в php.ini. Если ваша версия PHP старше, чем 5.2.4, установите ее на On:

display_errors = "On"

Если ваша версия 5.2.4 или новее, используйте:

display_errors = "stderr"

Обработка ошибок PHP

Иногда ваше приложение не запускается должным образом, что приводит к ошибке. Есть ряд причин, которые могут вызвать ошибки, например:

Веб-серверу может не хватить места на диске. Возможно, пользователь ввел недопустимое значение в поле формы. Файл или запись базы данных, к которой вы пытались получить доступ, может не существовать. Приложение может не иметь разрешения на запись в файл на диске A. служба, к которой приложение должно получить доступ, может быть временно недоступна. Эти типы ошибок известны как ошибки времени выполнения, поскольку они возникают во время выполнения сценария. Они отличаются от синтаксических ошибок, которые необходимо исправить перед запуском сценария.

Профессиональное приложение должно иметь возможность корректно обрабатывать такие ошибки времени выполнения. Обычно это означает более четкое и точное информирование пользователя о проблеме.

Понимание уровней ошибок

Обычно, когда возникает проблема, препятствующая правильной работе сценария, механизм PHP выдает ошибку. Каждая ошибка представлена ​​целым числом и связанной константой. В следующей таблице перечислены некоторые из распространенных уровней ошибок:

Механизм PHP вызывает ошибку всякий раз, когда он сталкивается с проблемой в вашем скрипте, но вы также можете инициировать ошибки самостоятельно, чтобы генерировать более удобные сообщения об ошибках. Таким образом вы можете сделать свое приложение более сложным. В следующем разделе описаны некоторые из распространенных методов, используемых для обработки ошибок в PHP:

Базовая обработка ошибок с помощью функции die()

<?php // Try to open a non-existent file
     $file = fopen("sample.txt", "r");
?>

Если файл не существует, вы можете получить такую ​​ошибку: Предупреждение: fopen(sample.txt) [function.fopen]: не удалось открыть поток: Нет такого файла или каталога в C:\wamp\www\project\test.php в строке 2

Если мы выполним несколько простых шагов, мы сможем предотвратить получение пользователями такого сообщения об ошибке:

<?php
if(file_exists("sample.txt")){
    $file = fopen("sample.txt", "r");
} else{
    die("Error: The file you are trying to access doesn't exist.");
}
?>

Теперь, если вы запустите указанный выше сценарий, вы получите следующее сообщение об ошибке:Ошибка: файл, к которому вы пытаетесь получить доступ, не существует.

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

Используемая выше функция die() просто отображает пользовательское сообщение об ошибке и завершает текущий скрипт, если файл sample.txt не найден.

Создание собственного обработчика ошибок

Вы можете создать свою собственную функцию обработчика ошибок, чтобы справиться с ошибкой времени выполнения, генерируемой механизмом PHP. Пользовательский обработчик ошибок обеспечивает большую гибкость и лучший контроль над ошибками, он может проверять ошибку и решать, что с ней делать, может отображать сообщение пользователю, регистрировать ошибку в файле или базе данных или отправлять по электронной почте. -mail, попытаться исправить проблему и продолжить, выйти из выполнения скрипта или вообще проигнорировать ошибку.

Функция пользовательского обработчика ошибок должна иметь возможность обрабатывать как минимум два параметра (errno и errstr), однако она может дополнительно принимать три дополнительных параметра (errfile, errline и errcontext), как описано ниже:

Вот пример простой пользовательской функции обработки ошибок. Этот обработчик customError() запускается всякий раз, когда возникает ошибка, какой бы тривиальной она ни была. Затем он выводит сведения об ошибке в браузер и останавливает выполнение сценария.

<?php
// Error handler function
function customError($errno, $errstr){
    echo "<b>Error:</b> [$errno] $errstr";
}
?>

Вам нужно указать PHP использовать вашу пользовательскую функцию обработчика ошибок - просто вызовите встроенную функцию set_error_handler(), передав имя функции.

<?php
// Error handler function
function customError($errno, $errstr){
    echo "<b>Error:</b> [$errno] $errstr";
}

// Set error handler
set_error_handler("customError");

// Trigger error
echo($test);
?>

Регистрация ошибок

Журнал сообщений об ошибках в текстовом файле

Вы также можете записать подробную информацию об ошибке в файл журнала, например:

<?php
function calcDivision($dividend, $divisor){
    if($divisor == 0){
        trigger_error("calcDivision(): The divisor cannot be zero", E_USER_WARNING);
        return false;
    } else{
        return($dividend / $divisor);
    }
}
function customError($errno, $errstr, $errfile, $errline, $errcontext){
    $message = date("Y-m-d H:i:s - ");
    $message .= "Error: [" . $errno ."], " . "$errstr in $errfile on line $errline, ";
    $message .= "Variables:" . print_r($errcontext, true) . "\r\n";

    error_log($message, 3, "logs/app_errors.log");
    die("There was a problem, please try again.");
}
set_error_handler("customError");
echo calcDivision(10, 0);
echo "This will never be printed.";
?>

Вызвать ошибку

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

Чтобы вызвать ошибку из сценария, вызовите функцию trigger_error(), передав сообщение об ошибке, которое вы хотите сгенерировать:

trigger_error("There was a problem.");

Рассмотрим следующую функцию, которая вычисляет деление двух чисел.

<?php
function calcDivision($dividend, $divisor){
    return($dividend / $divisor);
}

// Calling the function
echo calcDivision(10, 0);
?>

Если в качестве параметра $ divisor передается значение ноль (0), ошибка, генерируемая механизмом PHP, будет выглядеть примерно так:Предупреждение: деление на ноль в C:\wamp\www\project\test.php в строке 3

Это сообщение выглядит не очень информативным. Рассмотрим следующий пример, в котором для генерации ошибки используется функция trigger_error().

<?php
function calcDivision($dividend, $divisor){
    if($divisor == 0){
        trigger_error("The divisor cannot be zero", E_USER_WARNING);
        return false;
    } else{
        return($dividend / $divisor);
    }
}

// Calling the function
echo calcDivision(10, 0);
?>

Теперь сценарий генерирует это сообщение об ошибке:Предупреждение: делитель не может быть нулевым в C:\wamp\www\project\error.php в строке 4

Как видите, сообщение об ошибке, созданное во втором примере, более четко объясняет проблему по сравнению с предыдущим.

В дополнение к очень многим превосходным ответам, приведенным выше, вы также можете реализовать следующие две функции в своих проектах. Они будут ловить каждую несинтаксическую ошибку перед выходом из приложения / скрипта. Внутри функций вы можете сделать обратный след и войти или сделать приятное сообщение "Сайт находится на обслуживании" для общественности.

Фатальные ошибки:

register_shutdown_function

http://php.net/manual/en/function.register-shutdown-function.php

Ошибки:

set_error_handler

http://php.net/manual/en/function.set-error-handler.php

обратная трассировка:

debug_backtrace

http://php.net/manual/en/function.debug-backtrace.php

Включение отчетов об ошибках является правильным решением, однако, похоже, что оно не действует в программе, которая его включает, а только в последующих включенных программах.

Таким образом, я всегда создаю файл / программу (которую я обычно называю "genwrap.php"), в которой, по сути, используется тот же код, что и в популярном здесь решении (т. Е. Включаю отчет об ошибках), а затем он также включает страницу, которую я на самом деле хочу вызов.

Есть 2 шага для реализации этой отладки;

Один - создайте genwrap.php и поместите в него этот код:

<?php
error_reporting(-1);
ini_set('display_errors', 'On');

include($_REQUEST['page']);
?>

Два - измените ссылку на программу / страницу, которую вы хотите отладить, чтобы перейти через genwrap.php,

Например: изменить:

$.ajax('dir/pgm.php?param=val').done(function(data) { /* ... */

в

$.ajax('dir/genwrap.php?page=pgm.php&param=val').done(function(data) { /* ... */

Используйте Кинт. Это комбинация команд отладки на стероидах. https://kint-php.github.io/kint/ Это очень похоже на Nette Tracy

http://todell.com/debug может быть полезен. Вы можете видеть значения вашего объекта или брошенные ошибки отладки за кулисами даже в рабочем режиме.

Другие вопросы по тегам