get_exception_handler

Returns the callable currently registered as the exception handler, or null if none is set.

Signature
get_exception_handler(): ?callable
  • Added in PHP 8.5.0

Return value

?callableThe callable currently set as the exception handler — the exact value passed to set_exception_handler() — or null if no handler is defined.

So calling get_exception_handler() from inside your own handler returns null, not the running handler — the same way get_error_handler() behaves inside a running error handler, since PHP unsets that one too while it executes.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Verify in a test that a package removed its exception handler during teardown
  • Avoid double-registering a crash reporter during application bootstrap
  • Log which component owns uncaught exception handling in a plugin-heavy app

Frequently asked questions

How do I check the exception handler in PHP before 8.5?

Call $old = set_exception_handler(null) and then set_exception_handler($old). It works, but leaves a brief window with no handler installed, which get_exception_handler() removes.

Why does get_exception_handler return null inside my handler?

Since PHP 8.3 the active exception handler is unset for the duration of its own execution, so the lookup finds nothing. Reference the handler through a variable if you need it there.

Does get_exception_handler tell me if an exception is being handled?

No, it only reports which callable is registered. To know whether you are inside handling, track that yourself with a flag or check the argument your handler received.

More examples

Register a crash reporter only once

The guard turns a bootstrap that might run twice into an idempotent one. Without it, each call would push another handler onto the stack and the earlier ones would silently never run.

Example · php
<?php
function registerReporter(callable $reporter): bool {
    if (get_exception_handler() !== null) {
        return false;
    }
    set_exception_handler($reporter);
    return true;
}

$reporter = fn(Throwable $e) => print("reported: {$e->getMessage()}\n");
var_dump(registerReporter($reporter));   // true
var_dump(registerReporter($reporter));   // false - already registered
restore_exception_handler();

The handler is unset while it runs

Outside the handler the lookup finds the registered closure. Inside it, PHP has already unset the active handler (behaviour introduced in 8.3), so the same call returns NULL. Do not rely on self-lookup from within a handler.

Example · php
<?php
set_exception_handler(function (Throwable $e): void {
    echo 'handling: ', $e->getMessage(), "\n";
    var_dump(get_exception_handler());   // NULL, not the running handler
});

var_dump(get_exception_handler() !== null);   // bool(true) before the throw
throw new RuntimeException('database unreachable');

Which handler owns the process

Because the exact array callable is returned, you can print the owning class and method — useful in an application where several plugins may each try to install a handler. After restoring, the lookup returns NULL.

Example · php
<?php
class Crashes {
    public function report(Throwable $e): void { echo "crash: {$e->getMessage()}\n"; }
}

set_exception_handler([new Crashes(), 'report']);
$h = get_exception_handler();

echo is_array($h) ? $h[0]::class . '::' . $h[1] . "\n" : "closure\n";
restore_exception_handler();
var_dump(get_exception_handler());

Discussion

  • Be the first to comment on this lesson.