W3docs

getPrevious()

Функция PHP getPrevious() возвращает предыдущее исключение, переданное в конструктор текущего.

Введение

Exception::getPrevious() возвращает исключение, переданное в качестве третьего аргумента конструктору исключения PHP — то исключение, которое стало причиной текущего. Метод определён в базовом классе ExceptionError), поэтому все типы исключений PHP его наследуют.

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

Синтаксис и возвращаемое значение

final public Throwable::getPrevious(): ?Throwable
  • Параметры: отсутствуют.
  • Возвращает: предыдущий Throwable (исключение Exception или Error), если он был задан, иначе null.
  • Метод объявлен как final, поэтому переопределить его в собственных подклассах исключений невозможно.

«Предыдущее» исключение задаётся при создании исключения с третьим аргументом:

throw new RuntimeException("High-level failure", 0, $originalException);
//                          message            ^code  ^previous

Базовый пример

При повторном бросании исключения передавайте оригинальное в качестве третьего аргумента конструктора, чтобы не потерять контекст:

<?php
try {
    try {
        throw new Exception("Inner error");
    } catch (Exception $inner) {
        // Wrap the low-level error in a more meaningful one,
        // keeping the original as "previous".
        throw new Exception("Outer error", 0, $inner);
    }
} catch (Exception $e) {
    echo "Caught: " . $e->getMessage() . "\n";

    $previous = $e->getPrevious();
    if ($previous !== null) {
        echo "Caused by: " . $previous->getMessage() . "\n";
    }
}
?>

Вывод:

Caught: Outer error
Caused by: Inner error

getPrevious() возвращает объект $inner, переданный при создании, поэтому можно читать его сообщение, код или трассировку стека точно так же, как у любого другого исключения.

Зачем оборачивать исключения

Распространённый шаблон — перехватить низкоуровневое техническое исключение (ошибка запроса к базе данных, отсутствующий файл) и перебросить более высокоуровневое, предметное — не теряя при этом исходную причину:

<?php
function loadUser(int $id): array
{
    try {
        // Pretend this talks to a database and fails.
        throw new RuntimeException("SQLSTATE[HY000]: connection refused");
    } catch (RuntimeException $dbError) {
        // Callers care about "could not load user", not SQL internals,
        // but we keep the SQL error available via getPrevious().
        throw new RuntimeException("Unable to load user #$id", 0, $dbError);
    }
}

try {
    loadUser(42);
} catch (RuntimeException $e) {
    echo $e->getMessage() . "\n";
    echo "Root cause: " . $e->getPrevious()->getMessage() . "\n";
}
?>

Вывод:

Unable to load user #42
Root cause: SQLSTATE[HY000]: connection refused

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

Обход всей цепочки исключений

Предыдущее исключение само может иметь предыдущее. Чтобы исследовать всю цепочку, организуйте цикл, пока getPrevious() возвращает значение, отличное от null:

<?php
$a = new Exception("Level 1: low-level cause");
$b = new Exception("Level 2: mid-level wrapper", 0, $a);
$c = new Exception("Level 3: top-level error", 0, $b);

$current = $c;
while ($current !== null) {
    echo $current->getMessage() . "\n";
    $current = $current->getPrevious();
}
?>

Вывод:

Level 3: top-level error
Level 2: mid-level wrapper
Level 1: low-level cause

Распространённые ошибки

  • При отсутствии предыдущего исключения возвращается null. Если исключение создано без третьего аргумента, getPrevious() возвращает null. Всегда проверяйте условие !== null (или используйте цикл) перед вызовом методов на результате.
  • Третий аргумент конструктора — предыдущее исключение, а не код. Сигнатура: new Exception($message, $code, $previous). Распространённая ошибка — передать предыдущее исключение во второй слот, где PHP ожидает целочисленный код.
  • Метод доступен только для чтения. Метода setPrevious() не существует. Цепочка фиксируется в момент создания, поэтому причину нужно передавать при создании оборачивающего исключения.
  • var_dump($e) уже показывает цепочку. Когда необработанное исключение приводится к строке (или PHP выводит его сам), трассировка «Caused by» / предыдущего исключения включается автоматически — getPrevious() нужен тогда, когда требуется исследовать цепочку в коде.

Связанные методы

getPrevious() — один из нескольких методов инспекции, которые предоставляет каждое исключение PHP:

  • getMessage() — читаемое человеком сообщение об ошибке.
  • getCode() — числовой код ошибки.
  • getTrace() — трассировка стека в виде array.
  • getTraceAsString() — трассировка стека в виде string.

Более широкий контекст о try/catch и пользовательских классах исключений см. в разделе Исключения PHP.

Итоги

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

Практика

Практика
Что делает функция PHP getPrevious()?
Что делает функция PHP getPrevious()?
Was this page helpful?