Простой способ отладки программ на PHP

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

Главное при отладке программ и поиске «багов» — это терпение и последовательность в действиях. Если вы не будете соблюдать пошаговый алгоритм, то ничего не получится, в итоге вы запутаетесь и ни к чему не придёте.

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

Каждая метка выглядит примерно так

echo 1; // Отладочная метка
exit(); // Завершение работы скрипта

Интерпретатор кода PHP, дойдя до такой метки сделает следующее: выведя «1» в браузер, он немедленно прекратит выполнение кода программы. Таким образом, вы узнаете, что выполнение кода программы дошло до этого места, так как на экране будет выведена единичка и это будет последнее, что отобразится в браузере. Нет ничего проще, чтобы узнать — доходит ли до этой точки интерпретатор.

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

Дальнейшие действия могут быть следующими:

  • Можно переместить отладочную метку по коду ниже, чтобы выяснить — доходит ли интерпретатор до этой точки кода. Очень удобно, если вам надо выяснить факт срабатывания if() или факт входа в метод/функцию.
  • Можно выводить не «1», а что-то вроде «#1#» и потом искать его в исходном коде HTML браузера, чтобы не спутать отладочный вывод с обычным выводом (например, если страница содержит кучу других единичек).
  • Можно ставить сразу несколько меток в разных точках кода сразу, но эти метки непременно должны быть разные и желательно последовательные. Например, «#1#», «#2#», «#3#» и так далее. Так вы увидите в браузере все метки, до которых дошёл интерпретатор и сможете понять логику, которая в программе сработала.

Общее правило: продвигайтесь по коду очень медленно, стараясь не пропустить того момента, где таится баг. Старайтесь чаще использовать метод половинного деления.

Вывод значений переменных

Но что толку от того, что интерпретатор дошёл или не дошёл до какого-то места? Малоинформативно. Давайте добавим больше жизни!

Часто необходимо вывести значения конкретных переменных в конкретной точке кода. И тут нам пригодятся две мощнейшие функции — print_r() и var_dump(). Вот как их можно использовать.

Для того, чтобы увидеть содержимое переменной, используем print_r($var); или print_r($obj->var) если нужно посмотреть содержимое свойства конкретного объекта. Для того, чтобы увидеть значение true или false, используем var_dump(). Тут необходимо пояснить кое-что. Функция print_r() специально была придумана для того, чтобы красиво выводить значения разных типов. Причём она выводит и целые, и строки, и массивы и даже объекты. А вот true и false она не выводит, то есть вывод всегда будет равен пустой строке. Тут на помощь приходит var_dump(), который выводит точное значение и тип этого значения.

Использовать var_dump() везде я не рекомендую. Вывод, им генерируемый, выглядит намного запутаннее, чем вывод от print_r().

Итого, вот как будет выглядеть наша информативная метка:

echo  '#4#';
print_r($var1);
print_r($var2);
echo '@4@';

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

Можно ещё перед каждым print_r() выводить echo «var=»; чтобы понимать где и чьё значение отображается.

Замер времени выполнения части кода

Очень часто при профайлинге (а ещё чаще при поиске «тормозов» в коде) бывает необходимо замерить реальное время выполнения конкретного куска кода.

В PHP есть замечательная функция microtime(), которая возвращает текущее время в микросекундах. Если ей указать параметр true, то она будет возвращать его в виде числа с плавающей точкой, что нам и нужно.

Идея способа замера времени выполнения куска кода сводится к тому, чтобы запомнить текущее время перед началом этого куска и сравнить его с текущим временем в конце куска. То есть вот так:

$tt0 = microtime(true);
// ... код, который мы проверяем ....
$tt1 = microtime(true);
echo '#1#='.($tt1-$tt0);

При этом после метки мы увидим время, потраченное на выполнение кода в секундах. Часто вы будете видеть что-то типа такого: 1.233433E-05, это инженерная форма записи очень малых и очень больших чисел. Можно привести её в нормальный вид, добавив функцию sprintf():

echo '#1#='.sprintf('%.6f', $tt1-$tt0);

Немного больше кода, но зато вы будете видеть нормальные числа вроде 0.000012, т.е. 12 микросекунд.

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

Спасибо за внимание, не забудьте подписаться, чтобы не пропустить очередную статью!

Подписаться
Уведомить о
guest
2 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
Хима
Хима
10 лет назад

Тоже пользовался подобными «фишками», пока очень давно не увидел вижуал студио в режиме «дебаг» для асп дотнет проекта. После этого понял, что другие языки — не для меня.