Генеральный спонсор: Хостинг «Джино»

Система Orphus
Russian version
Добавить на Del.icio.us
English version
Добавить на Digg.com

 dkLab | Конструктор | Debug_HackerConsole: «хакерская» консоль, упрощающая отладку сайтов 

Карта сайта :: Форум «Лаборатории» :: Проект «Денвер»
Проект «Orphus» :: Куроводство: наблы :: Конструктор


4 сентября 2005 г.
Обсудить на форуме

1. Режимы оповещения об ошибках в PHP

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

  • Параметр display_errors (on или off) указывает, следует ли отображать сообщения об ошибках в браузере.
  • Параметр log_errors (on или off) заставляет PHP записывать сообщения в файл журнала (в mod_php по умолчанию это error_log, т.е. стандартный лог Apache для хранения сообщений об ошибках).
  • Директива error_reporting определяет, в каких случаях следует генерировать предупреждение, а в каких его можно проигнорировать.

Чайник 

Данные параметры можно выставлять не только в php.ini, но также и прямо во время работы скрипта, используя функцию ini_set().

Хорошо зарекомендовавший себя стиль заключается в следующем.

  • При разработке и отладке сайта на тестовом сервере включать display_errors и отключать — log_errors. Это позволяет программисту максимально быстро реагировать на возникновение ошибочной ситуации, минимизируя число «переключений между окнами».
  • При запуске сайта на «боевом» сервере в Интернете — наоборот, отключать display_errors, но включать log_errors. С одной стороны, это усложнит жизнь злоумышленникам, которые уже не смогут увидеть отладочную информацию. С другой — в критической ситуации поможет вам понять, что именно произошло, и исправить ошибку, даже если она не воспроизводится в тестовом окружении.

В обоих случаях error_reporting удобно выставлять в максимально «подробное» состояние — E_ALL, заставляющее PHP сообщать о самых незначительных оплошностях в коде.

Чайник 

Не стоит путать понятия «сообщение об ошибке» и «ошибка». Сообщение об ошибке — друг и союзник программиста, а не его враг. Чем больше сообщений мы видим, и чем более подробно они выводятся, тем проще нам отлаживать свои программы.

2. Отладочная информация

Используя одни лишь сообщения об ошибках и предупреждения, можно значительно ускорить отладку скриптов. Однако во многих случаях этого оказывается недостаточно: приходится по ходу работы сайта выводить еще какую-то информацию — «отладочные сообщения». Например, значения, принимаемые переменными программы в тех или иных ситуациях, лог SQL-запросов или статистика по времени работы отдельных участков скрипта. Возникает вопрос: куда выводить весь этот «хлам»?

Отображать диагностику прямо в браузер плохо: внешний вид HTML-страницы (верстка) от этого может сильно пострадать. К тому же вам придется все время включать в своем мозгу «блок распознавания образов», отделяя отладочные сообщения от текстов сайта.

Писать отладочную информацию в логи сервера (или в отдельный файл журнала) тоже не очень удобно: придется постоянно переключаться между окном браузера и окном просмотра журнала, «чистить» лог, искать в нем особенно интересные места и т. д. Особенно обидно, что часто полезна лишь малая доля отладочной информации, поэтому для варианта записи в лог-файл мы получим сильное его разрастание.

3. «Хакерская» консоль

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

Листинг 1
<?php
// Include library code.
include_once "../../lib/config.php";
require_once "Debug/HackerConsole/Main.php";

// Create & attach hacker conole to HTML output.
new Debug_HackerConsole_Main(true);

// Dump string values.
for ($i=0; $i<10; $i++) {
    $sp = str_repeat(' ', $i);
    Debug_HackerConsole_Main::out(
        "$sp\ti=$i", "Counting", "#008800"
    );
}

// Output to default group.
Debug_HackerConsole_Main::out("Usual message");

// Dump random structure.
Debug_HackerConsole_Main::out($_SERVER, "Input");
?>
<html>
<body style="margin:0px; padding:0px">
This is the test page with any text.<br>
Press Ctrl+~ (tilde) to toggle the console.<br>
Move mouse to console message to see its generator 
context (file, line, function name).
<hr>
<?show_source(__FILE__)?>
</body>
</html>

Зайдите на страницу этого примера. Вы увидите обычный HTML-документ. Теперь нажмите комбинацию клавиш Ctrl+~ (символ «тильда», располагается на клавиатуре слева от клавиши «единица»). Вы увидите, что в верхней части страницы открылась «хакерская консоль», в которой перечислен весь вывод, осуществленный скриптом по команде Debug_HackerConsole_Main::out(). Нажав ту же комбинацию еще раз, вы можете убрать консоль.

4. Основные возможности класса

Ниже перечислены основные возможности класса Debug_HackerConsole_Main.

  • Вы можете отображать в консоли не только значения скалярных переменных, но также и массивы. При этом безопасно использовать метод out() даже в обработчике ob_start(): вы не получите сообщение об «ошибке вложенного создания буферов», как при вызове известной функции PHP print_r().
  • Все сообщения, выводимые в консоль, объединяются в группы (второй параметр метода out()) для удобства отображения.
  • Можно задавать цвет текста выводимых сообщений (третий параметр).
  • Если навести мышь на некоторое сообщение и немного подождать, на экране «выскочит» подсказка, в которой будет написано, в каком файле и на какой строке сгенерировано сообщение.

    Чайник 

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

  • Если указать в конструкторе true, то создается новый обработчик выходного потока скрипта, в котором осуществляется «прикрепление» JavaScript-части консоли. При значении false перехват потока не осуществляется, и вы должны вручную «прикрепить» консоль к тексту страницы, используя метод attachToHtml().
  • В скрипте можно создавать несколько консолей, сохраняя созданные по new объекты. По умолчанию (при статическом вызове метода out() вида Debug_HackerConsole_Main::out() используется последняя созданная консоль. Конечно, вы можете вызывать out() и для произвольного консоль-объекта, задействовав команду $obj->out(...).
  • Табуляторы в тексте отладочных сообщений превращаются в корректное число пробелов, так, как это принято в текстовых редакторах.
  • Вы можете выделять мышью и копировать в буфер обмена текст из консоли. При дальнейшей вставке этого текста в любой редактор вы не получите лишних пустых строк или «съеденных» переносов, как это происходит при использовании стандартных HTML-тэгов <pre> и <xmp>.

5. Упрощение использования консоли

Особенно удобно использовать консоль для вывода лога всех SQL-запросов, выполненных скриптом. Если работа вашего сайта с СУБД идет через централизованную библиотеку, достаточно добавить вызов Debug_HackerConsole_Main::out() в функцию, осуществляющую SQL-запрос, чтобы получить хороший инструмент диагностики (особенно если вы будете логировать не только запросы, но также и результаты их выполнения в краткой форме вида «запрос возвратил X строк» или «запрос вернул ошибку Y»).

Но, конечно, писать в скриптах Debug_HackerConsole_Main::out() весьма неудобно — слишком длинно. Вы можете написать функцию с коротким именем (к примеру, debug()), которая будет «переадресовывать» вызов на метод out(). Однако, если сделать это «в лоб», вы обнаружите, что информация об имени файла и номере строки, сгенерировавшей сообщение, потерялась: она всегда будет указывать на место определения функции debug(), а не на место ее вызова.

Специально для того, чтобы решить эту проблему, класс Debug_HackerConsole_Main проверяет, вызван ли метод out() напрямую или же через call_user_func(). В последнем случае считается, что выполнена «переадресация», и отображается не контекст вызова out(), а контекст вызова функции, запустившей out(). В листинге приведен пример создания функции debug(), отображающей в консоль контекст своего вызова (online-демонстрация).

Листинг 2
<?php
// Include library code.
include_once "../../lib/config.php";
require_once "Debug/HackerConsole/Main.php";
new Debug_HackerConsole_Main(true);

// Dump random structure.
debug($_SERVER);

// Mediator function for short call of out() method
function debug($msg)
{
    // Use call_user_func_array() to save caller context.
    call_user_func(array('Debug_HackerConsole_Main', 'out'), $msg);
}
?>
Press Ctrl+~ (tilde) to toggle the console.<br>
Move mouse pointer to debug message and make sure that
caller context is NOT inside debug() definition, but
points to debug() calling point.
<hr>
<?show_source(__FILE__)?>







Дмитрий Котеров, Лаборатория dk. ©1999-2014
GZip
Добавить на Del.icio.us   Добавить на Digg.com   Добавить на reddit.com