W3docs

getTrace()

Узнайте, как Exception::getTrace() возвращает трассировку стека в виде массива, что содержит каждый фрейм и чем он отличается от getTraceAsString().

PHP getTrace()

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

На этой странице рассматривается, что возвращает getTrace(), структура каждого фрейма трассировки и чем он отличается от более привычного getTraceAsString(). Метод определён в базовом интерфейсе Throwable, поэтому он доступен для каждого объекта Exception и Error.

public Exception::getTrace(): array

Метод не принимает аргументов и возвращает индексированный массив. Фрейм 0 — самый внутренний вызов (функция, которая фактически выбросила исключение), а индексы растут по направлению к внешнему вызывающему коду.

Быстрый пример

Следующий скрипт выбрасывает исключение из вложенного вызова и выводит каждый фрейм трассировки:

<?php

function readConfig($path) {
    return parseFile($path);
}

function parseFile($path) {
    throw new Exception("Cannot read file: $path");
}

try {
    readConfig('/etc/app.conf');
} catch (Exception $e) {
    $trace = $e->getTrace();
    echo "Number of frames: " . count($trace) . "\n";
    foreach ($trace as $i => $frame) {
        echo "#$i {$frame['function']}() called in {$frame['file']} on line {$frame['line']}\n";
    }
}

Вывод:

Number of frames: 2
#0 parseFile() called in /path/to/script.php on line 4
#1 readConfig() called in /path/to/script.php on line 12

Обратите внимание: фрейм функции, которая выбросила исключение (parseFile), указывает строку, откуда она была вызвана (строка 4, внутри readConfig), а не строку с оператором throw. Строка выброса доступна отдельно через getLine() и getFile().

Что содержит каждый фрейм трассировки

Каждый фрейм является ассоциативным массивом. Наиболее полезные ключи:

КлючОписание
functionИмя функции или метода, который был вызван.
lineСтрока в file, откуда был сделан вызов.
fileФайл, откуда был сделан вызов.
classИмя класса (только для вызовов методов).
type-> для вызовов экземпляра, :: для статических вызовов.
argsМассив аргументов, переданных в вызов.

Следующий скрипт полностью инспектирует один фрейм:

<?php

function divide($a, $b) {
    if ($b === 0) {
        throw new InvalidArgumentException('Division by zero');
    }
    return $a / $b;
}

try {
    divide(10, 0);
} catch (Exception $e) {
    print_r($e->getTrace()[0]);
}

Вывод:

Array
(
    [file] => /path/to/script.php
    [line] => 11
    [function] => divide
    [args] => Array
        (
            [0] => 10
            [1] => 0
        )

)

Замечание по безопасности: запись args содержит фактические значения аргументов, которые могут включать пароли, токены или другие конфиденциальные данные. Никогда не передавайте сырой массив getTrace() конечным пользователям — вместо этого записывайте его на стороне сервера. Параметр INI zend.exception_ignore_args в PHP (включён по умолчанию начиная с PHP 7.4) удаляет args, чтобы избежать утечки чувствительных данных; если вы не видите ключ args, именно поэтому.

getTrace() vs getTraceAsString()

getTrace() возвращает сырой массив, который можно форматировать, фильтровать или сериализовать по своему усмотрению. Если вам нужна просто читаемая строка, используйте getTraceAsString(), который возвращает ту же информацию в предварительно отформатированном виде:

<?php

try {
    throw new RuntimeException('Something broke');
} catch (Throwable $e) {
    echo $e->getTraceAsString();
}

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

Место getTrace() в API исключений

getTrace() — один из нескольких доступных только для чтения методов-акцессоров каждого исключения. Они наиболее эффективны при совместном использовании внутри блока catch:

  • getMessage() — читаемое сообщение об ошибке.
  • getCode() — числовой код ошибки.
  • getFile() и getLine() — место выброса исключения.
  • getTraceAsString() — трассировка в виде строки.
  • getPrevious() — связанное исключение, если таковое имеется.

Для общего понимания выброса и перехвата исключений см. throw, try и класс Exception.

Лучшие практики обработки исключений в PHP

Чтобы ваш код был удобен в сопровождении и лёгок в отладке, важно следовать лучшим практикам при обработке исключений в PHP. Вот несколько советов, которые стоит помнить:

1. Используйте информативные сообщения исключений.

При выбрасывании исключения убедитесь, что сообщение информативно и полезно. Оно должно объяснять, что пошло не так и как это исправить. Например:

<?php

if ($someCondition) {
  throw new Exception('Invalid input: the email address is not valid.');
}

2. Перехватывайте только те исключения, которые можете обработать.

При перехвате исключений важно обрабатывать только те, с которыми вы умеете работать. Если перехватить исключение, которое вы не можете обработать, можно скрыть настоящую проблему и усложнить отладку. Например:

<?php

try {
  // Some code that may throw an exception.
} catch (InvalidArgumentException $e) {
  // Handle the invalid argument exception.
} catch (Exception $e) {
  // Handle all other exceptions.
}

3. Логируйте исключения.

Логирование исключений помогает диагностировать проблемы и устранять неполадки. Хорошей практикой является запись исключений в файл или базу данных для последующего анализа. Например:

<?php

try {
  // Some code that may throw an exception.
} catch (Exception $e) {
  error_log($e->getMessage(), 0);
}

4. Используйте иерархии исключений.

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

Заключение

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

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

Следуя этим лучшим практикам и используя метод getTrace(), вы сможете писать PHP-код, который является надёжным, устойчивым и простым в сопровождении. Обработка исключений может казаться незначительной деталью, но она способна существенно повлиять на качество и удобство использования вашего кода.

Practice

Практика
Какова цель функции getTrace() в PHP?
Какова цель функции getTrace() в PHP?
Was this page helpful?