<? phpukraine ДОКУМЕНТАЦІЯ
⌕Пошук по платформі
Документація українською

Переклад офіційної документації українською. Кожен розділ показує стан готовності: недоперекладене позначене відкрито, а не приховане.

МОВА · ПЕРЕКЛАДЕНО оновлено 30 вересня 2026

Винятки · PHP Manual

Дивіться також клас Exception.

Модель винятків у PHP схожа на ту, що є в інших мовах програмування. Виняток можна кинути (throw) і перехопити (catch) в межах PHP. Код можна огорнути в блок try, щоб перехопити можливі винятки. Кожен try повинен мати щонайменше один відповідний блок catch або finally.

Якщо виняток кинуто, а в поточній області видимості функції немає блоку catch, виняток «спливає» стеком викликів до функції, яка викликала поточну, доки не знайдеться відповідний блок catch. Усі блоки finally, які трапляться на цьому шляху, буде виконано. Якщо стек викликів розкрутиться аж до глобальної області видимості й відповідного блоку catch так і не знайдеться, програма завершиться фатальною помилкою, якщо тільки не встановлено глобальний обробник винятків.

Кинутий обʼєкт має бути instanceof Throwable. Спроба кинути обʼєкт, який ним не є, призведе до PHP Fatal Error.

Починаючи з PHP 8.0.0, ключове слово throw є виразом і може використовуватися в будь-якому контексті виразу. У попередніх версіях це була інструкція, яка мусила стояти окремим рядком.

catch

Блок catch визначає, як реагувати на кинутий виняток. У блоці catch вказують один або кілька типів винятку чи помилки, які він здатен обробити, і, за бажанням, змінну, якій буде присвоєно виняток. (До PHP 8.0.0 змінна була обовʼязковою.) Обʼєкт обробить перший блок catch, який трапиться кинутому винятку чи помилці й тип якого збігається з типом кинутого обʼєкта.

Кілька блоків catch дають змогу перехоплювати різні класи винятків. Звичайне виконання (коли в блоці try не кинуто жодного винятку) продовжиться після останнього блоку catch у послідовності. Усередині блоку catch винятки можна кидати (throw) або перекидати повторно. Якщо цього не зробити, виконання продовжиться після блоку catch, який спрацював.

Коли кинуто виняток, код після цієї інструкції не виконується, і PHP намагається знайти перший відповідний блок catch. Якщо виняток не перехоплено, буде видано PHP Fatal Error із повідомленням «Uncaught Exception ...», якщо тільки обробник не визначено функцією set_exception_handler().

Починаючи з PHP 7.1.0, блок catch може вказувати кілька винятків через символ вертикальної риски (|). Це зручно, коли різні винятки з різних ієрархій класів обробляються однаково.

Починаючи з PHP 8.0.0, імʼя змінної для перехопленого винятку є необовʼязковим. Якщо його не вказано, блок catch усе одно виконається, але не матиме доступу до кинутого обʼєкта.

finally

Блок finally можна також вказати після блоків catch або замість них. Код усередині блоку finally завжди виконується після блоків try і catch, незалежно від того, чи було кинуто виняток, і перед тим, як відновиться звичайне виконання.

Одна з помітних особливостей - взаємодія блоку finally з інструкцією return. Якщо return трапляється всередині блоку try або catch, блок finally все одно буде виконано. Більше того, інструкція return обчислюється в місці, де вона трапилася, але результат повертається після виконання блоку finally. До того ж, якщо блок finally теж містить return, повертається значення з блоку finally.

Інша помітна особливість - взаємодія винятку, кинутого в блоці try, і винятку, кинутого в блоці finally. Якщо обидва блоки кидають виняток, далі поширюватиметься виняток із блоку finally, а виняток із блоку try стане його попереднім винятком.

Глобальний обробник винятків

Якщо винятку дозволено спливти до глобальної області видимості, його може перехопити глобальний обробник винятків, якщо такий встановлено. Функція set_exception_handler() дає змогу задати функцію, яку буде викликано замість блоку catch, коли жоден інший блок не спрацював. Результат по суті такий самий, ніби вся програма огорнута в блок try-catch, де ця функція виконує роль catch.

Примітки

Внутрішні функції PHP переважно використовують звітування про помилки, винятки використовують лише сучасні обʼєктно-орієнтовані розширення. Утім, помилки легко перетворити на винятки за допомогою ErrorException. Цей прийом працює тільки з нефатальними помилками.

Приклад: перетворення звітування про помилки на винятки

<?php
function exceptions_error_handler($severity, $message, $filename, $lineno) {
    throw new ErrorException($message, 0, $severity, $filename, $lineno);
}

set_error_handler('exceptions_error_handler');

Стандартна бібліотека PHP (SPL) надає чимало вбудованих винятків.

Приклади

Приклад: кидання винятку

<?php
function inverse($x) {
    if (!$x) {
        throw new Exception('Division by zero.');
    }
    return 1/$x;
}

try {
    echo inverse(5) . "\n";
    echo inverse(0) . "\n";
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
}

// Продовжуємо виконання
echo "Hello World\n";

Результат виконання цього прикладу:

0.2
Caught exception: Division by zero.
Hello World

Приклад: обробка винятків із блоком finally

<?php
function inverse($x) {
    if (!$x) {
        throw new Exception('Division by zero.');
    }
    return 1/$x;
}

try {
    echo inverse(5) . "\n";
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
} finally {
    echo "First finally.\n";
}

try {
    echo inverse(0) . "\n";
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
} finally {
    echo "Second finally.\n";
}

// Продовжуємо виконання
echo "Hello World\n";

Результат виконання цього прикладу:

0.2
First finally.
Caught exception: Division by zero.
Second finally.
Hello World

Приклад: взаємодія блоку finally і return

<?php

function test() {
    try {
        throw new Exception('foo');
    } catch (Exception $e) {
        return 'catch';
    } finally {
        return 'finally';
    }
}

echo test();

Результат виконання цього прикладу:

finally

Приклад: вкладений виняток

<?php

class MyException extends Exception { }

class Test {
    public function testing() {
        try {
            try {
                throw new MyException('foo!');
            } catch (MyException $e) {
                // перекидаємо його далі
                throw $e;
            }
        } catch (Exception $e) {
            var_dump($e->getMessage());
        }
    }
}

$foo = new Test;
$foo->testing();

Результат виконання цього прикладу:

string(4) "foo!"

Приклад: обробка кількох винятків одним catch

<?php

class MyException extends Exception { }

class MyOtherException extends Exception { }

class Test {
    public function testing() {
        try {
            throw new MyException();
        } catch (MyException | MyOtherException $e) {
            var_dump(get_class($e));
        }
    }
}

$foo = new Test;
$foo->testing();

Результат виконання цього прикладу:

string(11) "MyException"

Приклад: пропуск змінної перехопленого винятку

Дозволено лише в PHP 8.0.0 і новіших версіях.

<?php

class SpecificException extends Exception {}

function test() {
    throw new SpecificException('Oopsie');
}

try {
    test();
} catch (SpecificException) {
    print "A SpecificException was thrown, but we don't care about the details.";
}

Результат виконання цього прикладу:

A SpecificException was thrown, but we don't care about the details.

Приклад: throw як вираз

Дозволено лише в PHP 8.0.0 і новіших версіях.

<?php

function test() {
    do_something_risky() or throw new Exception('It did not work');
}

function do_something_risky() {
    return false; // Імітуємо невдачу
}

try {
    test();
} catch (Exception $e) {
    print $e->getMessage();
}

Результат виконання цього прикладу:

It did not work

Приклад: виняток у try і у finally

<?php

try {
    try {
        throw new Exception(message: 'Third', previous: new Exception('Fourth'));
    } finally {
        throw new Exception(message: 'First', previous: new Exception('Second'));
    }
} catch (Exception $e) {
    var_dump(
        $e->getMessage(),
        $e->getPrevious()->getMessage(),
        $e->getPrevious()->getPrevious()->getMessage(),
        $e->getPrevious()->getPrevious()->getPrevious()->getMessage(),
    );
}

Результат виконання цього прикладу:

string(5) "First"
string(6) "Second"
string(5) "Third"
string(6) "Fourth"

Розширення винятків

Власний клас винятку визначають, розширюючи вбудований клас Exception. Наведені нижче члени й властивості показують, що доступне в дочірньому класі, похідному від вбудованого класу Exception.

Приклад: вбудований клас Exception

<?php
class Exception implements Throwable
{
    protected $message = '';                    // повідомлення винятку
    private   $string;                          // кеш __toString
    protected $code = 0;                        // визначений користувачем код винятку
    protected $file;                            // імʼя файлу з вихідним кодом, де стався виняток
    protected $line;                            // рядок вихідного коду, де стався виняток
    private   $trace;                           // стек викликів
    private   $previous;                        // попередній виняток, якщо виняток вкладений

    public function __construct($message = '', $code = 0, ?Throwable $previous = null);

    private function __clone();                 // Забороняє клонування винятків.

    final public  function getMessage();        // повідомлення винятку
    final public  function getCode();           // код винятку
    final public  function getFile();           // імʼя файлу з вихідним кодом
    final public  function getLine();           // рядок вихідного коду
    final public  function getTrace();          // масив backtrace()
    final public  function getPrevious();       // попередній виняток
    final public  function getTraceAsString();  // відформатований рядок зі стеком викликів

    // Можна перевизначати
    public function __toString();               // відформатований рядок для виведення
}

Якщо клас розширює вбудований клас Exception і перевизначає конструктор, наполегливо рекомендується також викликати parent::__construct(), щоб усі доступні дані було присвоєно належним чином. Метод __toString() можна перевизначити, щоб отримати власне виведення, коли обʼєкт подають як рядок.

Винятки не можна клонувати. Спроба клонувати виняток кидає Error, навіть якщо підклас оголошує власний метод __clone().

Приклад: розширення класу Exception

<?php
/**
 * Оголошуємо власний клас винятку
 */
class MyException extends Exception
{
    // Перевизначаємо виняток так, щоб повідомлення не було необовʼязковим
    public function __construct($message, $code = 0, ?Throwable $previous = null) {
        // якийсь код

        // переконуємося, що все присвоєно належним чином
        parent::__construct($message, $code, $previous);
    }

    // власне рядкове подання обʼєкта
    public function __toString() {
        return __CLASS__ . ": [{$this->code}]: {$this->message}\n";
    }

    public function customFunction() {
        echo "A custom function for this type of exception\n";
    }
}


/**
 * Створюємо клас для перевірки винятку
 */
class TestException
{
    public $var;

    const THROW_NONE    = 0;
    const THROW_CUSTOM  = 1;
    const THROW_DEFAULT = 2;

    function __construct($avalue = self::THROW_NONE) {

        switch ($avalue) {
            case self::THROW_CUSTOM:
                // кидаємо власний виняток
                throw new MyException('1 is an invalid parameter', 5);
                break;

            case self::THROW_DEFAULT:
                // кидаємо стандартний.
                throw new Exception('2 is not allowed as a parameter', 6);
                break;

            default:
                // Винятку немає, обʼєкт буде створено.
                $this->var = $avalue;
                break;
        }
    }
}


echo "# Example 1\n";
try {
    $o = new TestException(TestException::THROW_CUSTOM);
} catch (MyException $e) {      // Буде перехоплено
    echo "Caught my exception\n", $e;
    $e->customFunction();
} catch (Exception $e) {        // Пропущено
    echo "Caught Default Exception\n", $e;
}

// Продовжуємо виконання
var_dump($o); // Null


echo "\n\n# Example 2\n";
try {
    $o = new TestException(TestException::THROW_DEFAULT);
} catch (MyException $e) {      // Не збігається з цим типом
    echo "Caught my exception\n", $e;
    $e->customFunction();
} catch (Exception $e) {        // Буде перехоплено
    echo "Caught Default Exception\n", $e;
}

// Продовжуємо виконання
var_dump($o); // Null


echo "\n\n# Example 3\n";
try {
    $o = new TestException(TestException::THROW_CUSTOM);
} catch (Exception $e) {        // Буде перехоплено
    echo "Default Exception caught\n", $e;
}

// Продовжуємо виконання
var_dump($o); // Null


echo "\n\n# Example 4\n";
try {
    $o = new TestException();
} catch (Exception $e) {        // Пропущено, винятку немає
    echo "Default Exception caught\n", $e;
}

// Продовжуємо виконання
var_dump($o); // TestException
Стан перекладу

Перекладаємо з офіційної документації, розділ за розділом, і не ховаємо недоперекладене. Помітили неточність у терміні чи реченні: напишіть, виправимо.

48%
Готовності
1
У роботі
15
Ще не перекладено
Глосарій термінів