Oc-windows.ru

IT Новости из мира ПК
0 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Php стек вызовов

debug_backtrace — Выводит стек вызовов функций в массив

(PHP 4 >= 4.3.0, PHP 5, PHP 7)

debug_backtrace — Выводит стек вызовов функций в массив

Описание

debug_backtrace() выводит стек вызовов функций PHP в массив.

Список параметров

В версии 5.3.6, этот аргумент является битовой маской для следующих настроек:

Настройки debug_backtrace()

DEBUG_BACKTRACE_PROVIDE_OBJECTТребуется или нет заполнять данные «объектов».
DEBUG_BACKTRACE_IGNORE_ARGSТребуется или нет не выводить данные с индексом «args», то есть списки аргументов всех функций/методов, для уменьшения расхода памяти.

До версии 5.3.6 принимаются только значения TRUE или FALSE , которые означают, задана настройка DEBUG_BACKTRACE_PROVIDE_OBJECT или нет соответственно.

В версии 5.4.0, этот аргумент используется для ограничения количества вызовов функций, которые будут выведены. По умолчанию ( limit =) будет выведен весь стек вызовов.

Возвращаемые значения

Возвращает массив вложенных ассоциативных массивов ( array ). Описание элементов массива приведено ниже:

Список возможных значений элементов массивов, возвращаемых функцией debug_backtrace()

ИмяТипОписание
functionstringИмя текущей функции. См. также __FUNCTION__.
lineintegerТекущий номер строки. См. также __LINE__.
filestringИмя текущего файла. См. также __FILE__.
classstringИмя текущего класса. См. также __CLASS__
objectobjectТекущий объект.
typestringТекущий тип вызова функции. Если это вызов метода объекта, будет выведено «->». Если это вызов статического метода класса, то «::». Если это простой вызов функции, не выводится ничего.
argsarrayПри нахождении внутри функции, будет выведен список аргументов этой функции. Если внутри включаемого файла, будет выведен список включаемых файлов.

Список изменений

ВерсияОписание
5.4.0Добавлен необязательный аргумент limit .
5.3.6Аргумент provide_object заменен на options и добавлена дополнительная настройка DEBUG_BACKTRACE_IGNORE_ARGS .
5.2.5Добавлен необязательный аргумент provide_object .
5.1.1Элементом возвращаемого массива теперь может быть текущий объект object .

Примеры

Пример #1 Пример использования debug_backtrace()

function a_test ( $str )
<
echo «nHi: $str » ;
var_dump ( debug_backtrace ());
>

a_test ( ‘friend’ );
?>

// filename: /tmp/b.php
include_once ‘/tmp/a.php’ ;
?>

Результат аналогичен приведенному ниже, если запустить /tmp/b.php :

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

  • trigger_error() — Вызывает пользовательскую ошибку/предупреждение/уведомление
  • debug_print_backtrace() — Выводит стек вызовов функций

debug_print_backtrace

debug_print_backtrace — Выводит стек вызовов функций

Описание

debug_print_backtrace() выводит стек вызовов функций. Выводит вызовы функций, имена включенных/требуемых файлов и другую информацию из функций ( eval() ).

Список параметров

Начиная с PHP 5.3.6, этот аргумент является битовой маской для следующих настроек:

Опции debug_print_backtrace()

DEBUG_BACKTRACE_IGNORE_ARGSНужно ли исключить ключ «args», то есть списки аргументов всех функций/методов, чтобы уменьшить расход памяти.

Начиная с PHP 5.4.0, этот аргумент используется для ограничения количества вызовов функций, которые будут выведены. По умолчанию ( limit =) будет выведен весь стек вызовов.

Возвращаемые значения

Эта функция не возвращает значения после выполнения.

Список изменений

ВерсияОписание
5.4.0Добавлен необязательный аргумент limit .
5.3.6Добавлен необязательный аргумент options .

Примеры

Пример #1 Пример использования debug_print_backtrace()

function c () <
debug_print_backtrace ();
>

Результатом выполнения данного примера будет что-то подобное:

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

User Contributed Notes 7 notes

Another way to manipulate and print a backtrace, without using output buffering:

// print backtrace, getting rid of repeated absolute path on each file
$e = new Exception ();
print_r ( str_replace ( ‘/path/to/code/’ , » , $e -> getTraceAsString ()));
?>

I like the output of debug_print_backtrace() but I sometimes want it as a string.

bortuzar’s solution to use output buffering is great, but I’d like to factorize that into a function. Doing that however always results in whatever function name I use appearing at the top of the stack which is redundant.

Below is my noddy (simple) solution. If you don’t care for renumbering the call stack, omit the second preg_replace().

function debug_string_backtrace () <
ob_start ();
debug_print_backtrace ();
$trace = ob_get_contents ();
ob_end_clean ();

// Remove first item from backtrace as it’s this function which
// is redundant.
$trace = preg_replace ( ‘/^#0s+’ . __FUNCTION__ . «[^n]*n/» , » , $trace , 1 );

// Renumber backtrace items.
$trace = preg_replace ( ‘/^#(d+)/me’ , »#’ . ($1 — 1)’ , $trace );

This functionality is now implemented in the PEAR package PHP_Compat.

More information about using this function without upgrading your version of PHP can be found on the below link:

This code will give you a simple horizontal stack trace to assist debugging:

class A <
public function testA () <
echo «

  • Class A.testA —-??» ;
    echo «
  • » . $this -> whoDidThat ();
    >
    public function whoDidThat () <
    $who = debug_backtrace ();
    $result = «» ;
    $count = 0 ;
    $last = count ( $who );
    foreach( $who as $k => $v ) <
    if ( $count ++ > 0 ) <
    $x = «» ;
    if ( $count > 2 ) <
    $x = «>» ;
    >
    $result = «[line» . $who [ $k ][ ‘line’ ]. «]» . $who [ $k ][ ‘class’ ]. «.» . $who [ $k ][ ‘function’ ]. $x . $result ;
    >
    >
    return $result ;
    >
    >
    class B extends A <
    public function testB () <
    echo «
  • Class B.testB» ;
    echo «
  • » . $this -> whoDidThat ();
    >
    public function testA () <
    echo «
  • Class testB.testA —- Y» ;
    echo «
  • » . $this -> whoDidThat ();
    >
    >
    class C <
    public function test () <
    echo » » ;
    $b =new B ();
    echo » Class C calling B.testA» ;
    $b -> testA ();
    >
    >

    $c =new C ();
    $c -> test ();
    echo debug_print_backtrace ();
    ?>

    When run you get

    Class C calling B.testA
    *Class testB.testA —- Y
    *[line45]C.test>[line40]B.testA

    If you want to get the trace into a variable or DB, I suggest to do the following:

    ();
    debug_print_backtrace ();
    $trace = ob_get_contents ();
    ob_end_clean ();

    $query = sprintf ( «INSERT INTO EventLog (Trace) VALUES (‘%s’)» ,
    mysql_real_escape_string ( $trace ));
    mysql_query ( $query );
    ?>

    Here’s a function that returns a string with the same information shown in debug_print_backtrace(), with the option to exclude a certain amount of traces (by altering the $traces_to_ignore argument).

    I’ve done a couple of tests to ensure that it prints exactly the same information, but I might have missed something.

    This solution is a nice workaround to get the debug_print_backtrace() information if you’re already using ob_start() in your PHP code.

    function get_debug_print_backtrace ( $traces_to_ignore = 1 ) <
    $traces = debug_backtrace ();
    $ret = array();
    foreach( $traces as $i => $call ) <
    if ( $i $traces_to_ignore ) <
    continue;
    >

    $object = » ;
    if (isset( $call [ ‘class’ ])) <
    $object = $call [ ‘class’ ]. $call [ ‘type’ ];
    if ( is_array ( $call [ ‘args’ ])) <
    foreach ( $call [ ‘args’ ] as & $arg ) <
    get_arg ( $arg );
    >
    >
    >

    $ret [] = ‘#’ . str_pad ( $i — $traces_to_ignore , 3 , ‘ ‘ )
    . $object . $call [ ‘function’ ]. ‘(‘ . implode ( ‘, ‘ , $call [ ‘args’ ])
    . ‘) called at [‘ . $call [ ‘file’ ]. ‘:’ . $call [ ‘line’ ]. ‘]’ ;
    >

    return implode ( «n» , $ret );
    >

    function get_arg (& $arg ) <
    if ( is_object ( $arg )) <
    $arr = (array) $arg ;
    $args = array();
    foreach( $arr as $key => $value ) <
    if ( strpos ( $key , chr ( 0 )) !== false ) <
    $key = » ; // Private variable found
    >
    $args [] = ‘[‘ . $key . ‘] => ‘ . get_arg ( $value );
    >

    $arg = get_class ( $arg ) . ‘ Object (‘ . implode ( ‘,’ , $args ). ‘)’ ;
    >
    >
    ?>

    Отладка PHP-скриптов

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

    Оказывается, все достаточно просто. В PHP существует специальная функция set_error_handler(), которая позволяет задать свой собственный обработчик ошибок.Единственный ее параметр — это имя функции-обработчика, которая вызывается в случае возникновения ошибки. Функция-обработчик имеет 4 параметра: номер ошибки, текст ошибки, имя файла, в котором ошибка произошла и номер строки в этом файле.

    Но этих данных может быть недостаточно. Часто требуется вывести и весь стек вызовов, чтобы понять, где именно произошла ошибка. Получить стек вызвов можно с помощью функции debug_backtrace, которая возвращает массив обратных вызовов. Каждый элемент этого массива является хешем со следующими полями: function — имя функции, args — аргументы функции, file — имя файла скрипта, в котором она была вызвана. line — номер строки, где был выполнен вызов функции.

    Внимание: в ряде случаев file и line бывают не заданы, всегда проверяйте их (да и вообще любые индексы массива) с помощью isset, а константы — с помощью defined, иначе возникнет рекурсивный вызов обработчика ошибок. Кроме того, если сделать вывод аргументов функций, нужно принять меры, чтобы не выдавался пароль от базы данных в том случае, если ошибка возникнет на этапе подключения к СУБД (т.е. при вызове функции mysql_connect или ей подобной). Самый простой вариант — заменять его с помощью str_replace на звездочки или иные спецсимволы перед выводом.

    Рассмотрим пример функции-обработчика:

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

    Также часто при отладке скриптов требуется вывести значение какой-либо переменной, чтобы понять, на каком этапе берутся неправильные данные. Использование для этого print_r — не самое лучшее решение (особенно при отладке на живом сайте), так как значение может вывестись в неподходящем месте (например, если используется шаблонизатор, то еще до HTML-заголовка). Кроме того, Более корректное решение — запомнить значение в отладочную переменную, которую вывести потом там, где ее появление не будет мешать (например, в подвале сайта).

    Я для этих целей использую такую функцию:

    Эта функция экранирует все переданные в нее параметры и запоминает в глобальную переменную $GLOBALS[‘IntBF_debug’], из которой ее можно вывести в любом подходящем месте с помощью обычного echo.

    Если требуется прервать выполнение скрипта с ошибкой по инициативе разработчика (например, после ошибочного SQL-запроса), следует использовать функцию trigger_error. У этой функции два параметра: первый — строка с сообщением об ошибке, которая будет передана в параметр $errstr обработчика, а второй — код ошибки, который может быть одной из трех констант: E_USER_ERROR (приведет к завершению выполнения), E_USER_WARNING, E_USER_NOTICE.

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

    Tracing PHP Applications with xdebug

    Добро пожаловать во вторую серию нашего повествования про xdebug. Установка xdebug и его базовые возможности были рассмотрены в первой серии. В данной статье мы рассмотрим трассировку программы.
    Предыдущая серия цикла Introducing xdebug

    Создание лога трассировки

    Вместо ручного добавления различных функций вывода отладочной информации мы можем воспользоваться xdebug для создания лога трассировки. Лог трассировки это список вызовов функций и методов класса на всем протяжении выполнения скрипта. Преимущество заключается в том, что каждый вызов найдет свое отражение в логе
    Лог трассировки обычно различается от запуска к запуску, так как он зависит от входящих данных, которые различаются от запроса к запросу.
    Отслеживание лога трассировки помогает нам понять, как происходит выполнение нашей программы, однако очень сложно визуализировать все возможные ветвления, если только наша программа не является очень простой. Один if предполагает два возможных пути развития программы. С каждым дальнейшим if количество (теоретически) возможных путей развития умножается на 2. Именно из-за этого тестирование больших программ достаточно сложно: слишком много различный путей развития и каждый необходимо протестировать.
    А сейчас приступим к созданию лога трассировки. xdebug поддерживает два различных формата для логов. По умолчанию логии создаются в приятном для человеческого глаза формате, их удобно читать и анализировать. Если вы хотите обработать лог трассировки какой-либо программой (предназначенной для обработки логов xdebug), необходимо сконфигурировать xdebug в другом формате. Такой формат (computer-readable) легко обрабатывается программой (анализатором логов), потому что он содержит колонки фиксированной длины
    Если вы хотите получить лог трассировки для каждого запускаемого вами скрипта, добавьте следующие команды

    в php.ini. Не забудьте перестартовать ваш веб-сервер после изменения php.ini.
    Вторая строка определяет путь, по которому xdebug будет сохранять логи. По умолчанию этот путь установлен в /tmp, это хороший выбор для, но вызовет проблемы в Windows, так как c:tmp (считается что c: это текущий диск) обычно не создана. Поэтому необходимо создать каталог в Windows (или прописать существующий), в который xdebug будет сохранять логии трассировки, иначе ничего не получится.
    Выполнение функций и методов будут очень медленными так как каждый их вызов, а также результаты будут записаны в лог.

    Трассировка части приложения

    Так как размер лога трассировки очень быстро растет, хорошим решением является создать лог только для «интересных» частей приложения, например, создание лога трассировки на этапе инициализации.
    Давайте посмотрим как создать лог трассировки для маленькой рекурсивной функции (вычисление факториала), в данном примере мы начнем и закончим трассировку в реальном времени. Если вы активировали трассировку в php.ini, вы увидите предупреждение, что трассировка уже начата для вашего скрипта.

    function fac($x)
    <
    if (0 == $x) return 1;
    return $x * fac($x — 1);
    >

    TRACE START [2007-10-26 12:18:48]
    0.0068 53384 -> fac() C:wwwfac.php:5
    0.0069 53584 -> fac() C:wwwfac.php:10
    0.0069 53840 -> fac() C:wwwfac.php:10
    0.0070 54096 -> fac() C:wwwfac.php:10
    0.0070 54376 -> fac() C:wwwfac.php:10
    0.0071 54656 -> fac() C:wwwfac.php:10
    0.0072 54936 -> fac() C:wwwfac.php:10
    0.0072 55216 -> fac() C:wwwfac.php:10
    0.0073 55392 -> xdebug_stop_trace() C:wwwfac.php:13
    0.0237 55392
    TRACE END [2007-10-26 12:18:48]

    в php.ini. Разница – это различие между использованием памяти между текущей строкой и предыдущей. Вы можете добавить данную настройку во время выполнения используя функцию ini_set, но только после того как начнется трассировка.
    Функция xdebug_start_trace имеет второй необязательный параметр. Вы можете использовать один или больше из трех следующих настроек: XDEBUG_TRACE_APPEND добавляет к существующему файлу трассировки. Когда установлен XDEBUG_TRACE_COMPUTERIZED, xdebug создает лог трассировки в формате удобном для чтения программой-анализатором. Использование этого параметра такое же, как и установка параметра xdebug.trace_format в 1. Параметр XDEBUG_TRACE_HTML устанавливает формат лога трассировки в виде HTML.
    Следующий скриншот показывает HTML-формат лога трассировки:

    Добавление информации в лог трассировки

    Также мы может настроить xdebug, чтобы он сохранял нам параметры, которые мы передаем в функции. Это очень полезно чтобы лучше понимать, как происходит выполнение программы.
    Сохранение параметров в лог трассировки устанавливается параметром xdebug.collect_params, о котором было описано в предыдущей статье. xdebug.collect_params принимает числовые значения, 0 означает никакой дополнительной информации, 4 означает, что необходимо отобразить название переменной и всю информацию о каждом параметре функции. Значение 3 будет отображать имена и значения переменных, обрезанных в соответствие с настройками параметров xdebug.var_display_max_data, debug.var_display_max_children и xdebug.var_display_max_depth, описанных в предыдущей статье.
    Ниже выдержка из лога трассировки с сохранением параметров функций:

    0.0033 54320 -> fac($x = 7) C:wwwfac.php:6
    0.0034 54432 -> fac($x = 6) C:wwwfac.php:11

    TRACE START [2007-10-26 12:30:04]
    0.0133 55704 +48 -> fac($x = 7) C:wwwfac.php:8
    0.0133 55840 +136 -> fac($x = 6) C:wwwfac.php:13
    0.0134 56096 +256 -> fac($x = 5) C:wwwfac.php:13
    0.0134 56352 +256 -> fac($x = 4) C:wwwfac.php:13
    0.0134 56632 +280 -> fac($x = 3) C:wwwfac.php:13
    0.0135 56912 +280 -> fac($x = 2) C:wwwfac.php:13
    0.0135 57192 +280 -> fac($x = 1) C:wwwfac.php:13
    0.0135 57472 +280 -> fac($x = 0) C:wwwfac.php:13
    >=> 1
    >=> 1
    >=> 2
    >=> 6
    >=> 24
    >=> 120
    >=> 720
    >=> 5040
    0.0140 57648 +176 -> xdebug_stop_trace() C:wwwfac.php:26
    0.0140 57648
    TRACE END [2007-10-26 12:30:04]

    Как вы видите в данном примере установлен параметр xdebug.show_mem_delta.

    Озаглавливание лога трассировки

    До текущего момента, мы явно указывали название лога трассировки. Это не всегда удобно. Если вам необходимо рассматривать логи в зависимости от входящих данных или состояния приложения, неплохо чтобы сам xdebug автоматически присваивал название. xdebug может присваивать имя в зависимости от того что вы используете, параметр xdebug.auto_trace или функцию xdebug_start_trace() для активации трассировки. Если в последнем примере передать пустой аргумент в качестве параметров функции xdebug_start_trace, xdebug автоматически выберет имя для файла.
    Название файла сгенерированного xdebug всегда начинается с «trace.» и имеет расширение .xt. Часть имени между точками по умолчанию это CRC от рабочего каталога. Устанавливая xdebug.trace_output_name вы можете определить другое имя для лога трассировки. xdebug.trace_output_name принимает строку в качестве аргумента, строка может содержать различные спецификаторы. Ниже список самых важных спецификаторов:

    • %c — CRC рабочего каталога
    • %p – идентификатор процесса
    • %r – некое случайное число
    • %u – текущее время с микросекундами
    • %H — $_SERVER[‘HTTP_HOST’]
    • %R — $_SERVER[‘REQUEST_URI’]

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

    в php.ini.
    Если вам необходимо знать во время запуска какое имя выберет xdebug для записи лога, вы можете вызвать функцию xdebug_get_tracefile_name().

    Заключение

    Возможность использовать трассировку функций это очень полезная вещь, которую нам предоставляет xdebug. Вы можете создавать логии ваших программ без добавления вызовов различных функций. Все вызовы функций будут отображены без явных вызовов функций отображения справочной информации.
    Вы можете использовать различные утилиты подобные grep чтобы найти необходимую информацию или секцию в логе трассировки, или написать маленькую программку на PHP, которая будет разбирать этот файл для вас. Трассировка это не замена отладчику. Отладчик будет рассмотрен в четвертой части повествования.
    Вы не должны активировать трассировку на боевых машинах, это очень сильно ухудшит производительность, каждая строка программы будет отражена в логе трассировки.
    Следующая статья будет посвящена Profiling PHP Applications With xdebug.

    Читать еще:  Снять защиту doc
  • Ссылка на основную публикацию
    Adblock
    detector