Как дебажить PHP
Содержание
Отладка ошибки 500 при помощи register_shutdown_function
Иногда причину 500 ошибки можно определить при помощи вывода последней ошибки, которая произошла перед завершением скрипта. Для ее вывода в начало выполняемого PHP файла необходимо добавить следующий код:
register_shutdown_function(function(){
if (error_get_last()) {
var_export(error_get_last());
}
});
Данный код регистрирует функцию, которая будет выполняться по завершении скрипта. В функции происходит вывод последней ошибки, которая была зафиксирована при выполнении скрипта.
Документация по register_shutdown_function
Вывод данных отладки в браузере
Наиболее простой способ вывести любую переменную это функции print_r(), var_dump() и var_export()
print_r() - выводит структуру переменной в удобочитаемом виде
var_dump() - также выводит тип данных для всех переменных
var_export() - выводит структуру переменно в формате пригодным для выполнения в PHP
По умолчанию выводы этих функций используют '\n' в качестве переносов на новую строку.
Так как в браузере эти символы удаляются, то для того, чтобы результат было удобно читать, можно поместить его в тег <pre>
echo '<pre>';
print_r($var);
echo '</pre>';
или так
echo '<pre>' . print_r($var, true) . '</pre>';
В качестве второго аргумента для функций print_r() и var_export() можно указать true, если необходимо, чтобы функция возвращала результат, а не выводила его.
Код:
echo '<pre>';
print_r($variables['user']);
var_dump($variables['user']);
var_export($variables['user']);
echo '</pre>';
Результат вывода:
Array
(
[id] => 3
[type] => guest
)
array(2) {
["id"]=>
int(3)
["type"]=>
string(5) "guest"
}
array (
'id' => 3,
'type' => 'guest',
)
Иногда необходимо вывести все доступные в текущей области видимости переменные, в этом случае можно воспользоваться функцией get_defined_vars
Документация по get_defined_vars
Вывод данных отладки в файл
Иногда вывести переменные в браузер нет возможности: важно не нарушать работу сайта, либо скрипт выполняет редирект на другую станицу, а также по другим причинам.
Для записи данных отладки в файл нам поможет функция file_put_contents, можно использовать ее со следующими аргументами:
file_put_contents("umitest", print_r($variable, true)."\n", FILE_APPEND | LOCK_EX);
В результате выполнения данной функции рядом с файлом, из которого было запущено выполнение PHP (обычно это index.php в корне сайта), будет создан файл umitest в который запишется содержимое переменной $variable.
FILE_APPEND - сообщает о том, что данные необходимо записывать в конец файла, без него файл будет каждый раз перезаписываться.
LOCK_EX - блокирует файл для записи, чтобы в него не смогли писать другие скрипты.
Можно вывести в файл все переменные, доступные в текущей области видимости:
file_put_contents("umitest", print_r(get_defined_vars(), true)."\n", FILE_APPEND | LOCK_EX);
или только некоторые из них
file_put_contents("umitest", print_r([$var1,$var2], true)."\n", FILE_APPEND | LOCK_EX);
Документация по file_put_contents
Получить стек вызова функции при помощи debug_backtrace
Данная функция может помочь нам, если мы знаем, какая функция вызывается, но не знаем, откуда она вызывается, а также просто проследить цепочку вызова функций. При вызове этой функции без параметров можно легко получить переполнение памяти, поэтому необходимо вызвать эту функцию с указанием первого аргумента DEBUG_BACKTRACE_IGNORE_ARGS
$debug_arr = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS)
Также в качестве второго аргумента можно указать глубину стека.
Стек вызова можно вывести как в браузер:
echo '<pre>' . print_r(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), true) . '</pre>';
так и записывать в файл:
file_put_contents("umitest", print_r(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), true), FILE_APPEND | LOCK_EX);
Документация по debug_backtrace
Время выполнения скрипта
Иногда необходимо проверить, за сколько времени выполняется тот или иной участок кода. Для этого можно воспользоваться следующим кодом:
$start = microtime(true);
// тут код время выполнения которого необходимо посчитать
$stop = microtime(true) - $start;
file_put_contents("umitest", print_r($stop, true)."\n", FILE_APPEND | LOCK_EX);