Debug backtrace: примеры (PHP)

Полное руководство по debug_backtrace в PHP
Раздел: Отладка
debug_backtrace(int $options = DEBUG_BACKTRACE_PROVIDE_OBJECT, int $limit = 0): array
Описание функции debug_backtrace

Функция debug_backtrace() возвращает массив с трассировкой стека вызовов. Эта функция полезна для отладки, когда нужно определить, какой код вызвал определенную функцию или метод.

Когда используется

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

Аргументы функции

Функция принимает два необязательных параметра:

  1. options - целочисленный битовый флаг:
    • DEBUG_BACKTRACE_PROVIDE_OBJECT (по умолчанию) - включает объекты в стек вызовов
    • DEBUG_BACKTRACE_IGNORE_ARGS - исключает аргументы функций из результата
  2. limit - ограничивает количество возвращаемых записей стека. В PHP 7+ по умолчанию 0 (без ограничений).
Базовые примеры использования
Пример 1: Простая трассировка

Код:

<?php
function a() {
    b();
}
function b() {
    c();
}
function c() {
    var_dump(debug_backtrace());
}
a();
?>

Результат:

array(3) {
  [0]=> array(4) {
    ["file"]=> string(9) "test.php"
    ["line"]=> int(10)
    ["function"]=> string(1) "c"
    ["args"]=> array(0) {}
  }
  [1]=> array(4) {
    ["file"]=> string(9) "test.php"
    ["line"]=> int(6)
    ["function"]=> string(1) "b"
    ["args"]=> array(0) {}
  }
  [2]=> array(4) {
    ["file"]=> string(9) "test.php"
    ["line"]=> int(3)
    ["function"]=> string(1) "a"
    ["args"]=> array(0) {}
  }
}
Пример 2: С игнорированием аргументов

Код:

<?php
function test($param1, $param2) {
    print_r(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS));
}
test('secret', 'password');
?>

Результат:

Array
(
    [0] => Array
        (
            [file] => test.php
            [line] => 4
            [function] => test
        )
)
Похожие функции в PHP

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

Exception::getTrace

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

xdebug_get_function_stack

Расширение Xdebug предоставляет эту функцию с дополнительной информацией, включая время выполнения, память и переменные.

Типичные ошибки
Игнорирование производительности

Код:

<?php
function process() {
    // Многократный вызов в цикле
    for($i = 0; $i < 10000; $i++) {
        $trace = debug_backtrace();
    }
}
process(); // Заметное замедление выполнения
?>

Функция ресурсоемкая, частые вызовы замедляют приложение.

Неправильная интерпретация уровней

Код:

<?php
function getCaller() {
    $trace = debug_backtrace();
    // Ожидается, что индекс 0 - текущая функция
    // Индекс 1 - вызывающая функция
    return $trace[1]['function'];
}
?>

Может вызвать ошибку, если стек содержит меньше двух уровней.

Изменения в последних версиях PHP

В PHP 7.0 добавлен параметр limit для ограничения количества возвращаемых записей.

В PHP 5.4 добавлена константа DEBUG_BACKTRACE_IGNORE_ARGS.

В PHP 5.3.6 изменено значение по умолчанию для provide_object с FALSE на TRUE.

В PHP 5.2.5 добавлена константа DEBUG_BACKTRACE_PROVIDE_OBJECT.

Расширенные примеры
Пример 1: Кастомный логгер с трассировкой

Код:

Пример php
<?php
class Logger {
    public static function log($message) {
        $trace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 2);
        $caller = $trace[1];
        
        $logMessage = sprintf(
            "[%s] %s in %s:%d",
            date('Y-m-d H:i:s'),
            $message,
            $caller['file'],
            $caller['line']
        );
        
        file_put_contents('app.log', $logMessage . PHP_EOL, FILE_APPEND);
    }
}

function processOrder($orderId) {
    // Логирование с контекстом
    Logger::log("Processing order #$orderId");
}

processOrder(123);
?>
Пример 2: Определение вызывающего класса

Код:

Пример php
<?php
class Validator {
    public function validate() {
        $trace = debug_backtrace();
        
        foreach($trace as $call) {
            if(isset($call['class'])) {
                echo "Вызывающий класс: " . $call['class'] . "\n";
                break;
            }
        }
    }
}

class UserService {
    public function createUser() {
        $validator = new Validator();
        $validator->validate();
    }
}

$service = new UserService();
$service->createUser();
?>

Результат:

Вызывающий класс: UserService
Пример 3: Анализ вложенных вызовов

Код:

Пример php
<?php
function analyzeStack() {
    $trace = debug_backtrace();
    
    echo "Глубина стека: " . count($trace) . "\n";
    echo "Путь вызовов:\n";
    
    foreach(array_reverse($trace) as $index => $call) {
        $function = $call['function'] ?? 'unknown';
        $class = $call['class'] ?? '';
        $type = $call['type'] ?? '';
        
        echo sprintf("%d. %s%s%s()\n", 
            $index + 1, 
            $class, 
            $type, 
            $function
        );
    }
}

class A {
    public static function method1() {
        B::method2();
    }
}

class B {
    public static function method2() {
        analyzeStack();
    }
}

A::method1();
?>

Результат:

Глубина стека: 3
Путь вызовов:
1. A::method1()
2. B::method2()
3. analyzeStack()
Аналоги в других языках
JavaScript: console.trace

Код:

function a() {
    b();
}
function b() {
    console.trace();
}
a();

Результат в консоли браузера показывает стек вызовов.

Python: traceback.extract_stack

Код:

import traceback

def a():
    b()

def b():
    for line in traceback.extract_stack():
        print(line)

a()

Результат:

<stdin>(6, b, None)
<stdin>(3, a, None)
<stdin>(9, <module>, None)
Java: Thread.currentThread().getStackTrace()

Возвращает массив элементов StackTraceElement, содержащих информацию о стеке вызовов текущего потока.

PHP debug_backtrace function comments

En
Debug backtrace Generates a backtrace