1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Add get_error_handler(), get_exception_handler() functions

RFC: https://wiki.php.net/rfc/get-error-exception-handler

Closes GH-17693
This commit is contained in:
Arnaud Le Blanc
2025-02-04 12:43:33 +01:00
parent 5e56c3e7bf
commit 14fc50e732
7 changed files with 214 additions and 1 deletions

1
NEWS
View File

@@ -40,6 +40,7 @@ PHP NEWS
. Fixed bug GH-18026 (Improve "expecting token" error for ampersand). (ilutov)
. Added the (void) cast to indicate that not using a value is intentional.
(timwolla)
. Added get_error_handler(), get_exception_handler() functions. (Arnaud)
- Curl:
. Added curl_multi_get_handles(). (timwolla)

View File

@@ -244,6 +244,12 @@ PHP 8.5 UPGRADE NOTES
6. New Functions
========================================
- Core:
. get_error_handler() allows retrieving the current user-defined error handler
function
. get_exception_handler() allows retrieving the current user-defined exception
handler function
- Curl:
. curl_multi_get_handles() allows retrieving all CurlHandles current
attached to a CurlMultiHandle. This includes both handles added using

View File

@@ -0,0 +1,88 @@
--TEST--
get_error_handler()
--FILE--
<?php
class C {
function handle() {}
static function handleStatic() {}
}
class Invokable {
public function __invoke() {
}
}
function foo() {}
echo "No error handler\n";
var_dump(get_error_handler() === null);
echo "\nFunction string\n";
set_error_handler('foo');
var_dump(get_error_handler() === 'foo');
echo "\nNULL\n";
set_error_handler(null);
var_dump(get_error_handler() === null);
echo "\nStatic method array\n";
set_error_handler([C::class, 'handleStatic']);
var_dump(get_error_handler() === [C::class, 'handleStatic']);
echo "\nStatic method string\n";
set_error_handler('C::handleStatic');
var_dump(get_error_handler() === 'C::handleStatic');
echo "\nInstance method array\n";
set_error_handler([$c = new C(), 'handle']);
var_dump(get_error_handler() === [$c, 'handle']);
echo "\nFirst class callable method\n";
set_error_handler($f = (new C())->handle(...));
var_dump(get_error_handler() === $f);
echo "\nClosure\n";
set_error_handler($f = function () {});
var_dump(get_error_handler() === $f);
echo "\nInvokable\n";
set_error_handler($object = new Invokable());
var_dump(get_error_handler() === $object);
echo "\nStable return value\n";
var_dump(get_error_handler() === get_error_handler());
?>
==DONE==
--EXPECT--
No error handler
bool(true)
Function string
bool(true)
NULL
bool(true)
Static method array
bool(true)
Static method string
bool(true)
Instance method array
bool(true)
First class callable method
bool(true)
Closure
bool(true)
Invokable
bool(true)
Stable return value
bool(true)
==DONE==

View File

@@ -0,0 +1,87 @@
--TEST--
get_exception_handler()
--FILE--
<?php
class C {
function handle() {}
static function handleStatic() {}
}
class Invokable {
public function __invoke() {
}
}
function foo() {}
echo "No exception handler\n";
var_dump(get_exception_handler() === null);
echo "\nFunction string\n";
set_exception_handler('foo');
var_dump(get_exception_handler() === 'foo');
echo "\nNULL\n";
set_exception_handler(null);
var_dump(get_exception_handler() === null);
echo "\nStatic method array\n";
set_exception_handler([C::class, 'handleStatic']);
var_dump(get_exception_handler() === [C::class, 'handleStatic']);
echo "\nStatic method string\n";
set_exception_handler('C::handleStatic');
var_dump(get_exception_handler() === 'C::handleStatic');
echo "\nInstance method array\n";
set_exception_handler([$c = new C(), 'handle']);
var_dump(get_exception_handler() === [$c, 'handle']);
echo "\nFirst class callable method\n";
set_exception_handler($f = (new C())->handle(...));
var_dump(get_exception_handler() === $f);
echo "\nClosure\n";
set_exception_handler($f = function () {});
var_dump(get_exception_handler() === $f);
echo "\nInvokable\n";
set_exception_handler($object = new Invokable());
var_dump(get_exception_handler() === $object);
echo "\nStable return value\n";
var_dump(get_exception_handler() === get_exception_handler());
?>==DONE==
--EXPECT--
No exception handler
bool(true)
Function string
bool(true)
NULL
bool(true)
Static method array
bool(true)
Static method string
bool(true)
Instance method array
bool(true)
First class callable method
bool(true)
Closure
bool(true)
Invokable
bool(true)
Stable return value
bool(true)
==DONE==

View File

@@ -1322,6 +1322,15 @@ ZEND_FUNCTION(restore_error_handler)
}
/* }}} */
ZEND_FUNCTION(get_error_handler)
{
ZEND_PARSE_PARAMETERS_NONE();
if (Z_TYPE(EG(user_error_handler)) != IS_UNDEF) {
RETURN_COPY(&EG(user_error_handler));
}
}
/* {{{ Sets a user-defined exception handler function. Returns the previously defined exception handler, or false on error */
ZEND_FUNCTION(set_exception_handler)
{
@@ -1368,6 +1377,15 @@ ZEND_FUNCTION(restore_exception_handler)
}
/* }}} */
ZEND_FUNCTION(get_exception_handler)
{
ZEND_PARSE_PARAMETERS_NONE();
if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
RETURN_COPY(&EG(user_exception_handler));
}
}
static inline void get_declared_class_impl(INTERNAL_FUNCTION_PARAMETERS, int flags) /* {{{ */
{
zend_string *key;

View File

@@ -117,11 +117,15 @@ function set_error_handler(?callable $callback, int $error_levels = E_ALL) {}
function restore_error_handler(): true {}
function get_error_handler(): ?callable {}
/** @return callable|null */
function set_exception_handler(?callable $callback) {}
function restore_exception_handler(): true {}
function get_exception_handler(): ?callable {}
/**
* @return array<int, string>
* @refcount 1

View File

@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 3dbc84896823c9aaa9ac8aeef8841266920c3e50 */
* Stub hash: a24761186f1ddf758e648b0a764826537cbd33b9 */
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_exit, 0, 0, IS_NEVER, 0)
ZEND_ARG_TYPE_MASK(0, status, MAY_BE_STRING|MAY_BE_LONG, "0")
@@ -148,12 +148,17 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_restore_error_handler, 0, 0, IS_TRUE, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_get_error_handler, 0, 0, IS_CALLABLE, 1)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_set_exception_handler, 0, 0, 1)
ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 1)
ZEND_END_ARG_INFO()
#define arginfo_restore_exception_handler arginfo_restore_error_handler
#define arginfo_get_exception_handler arginfo_get_error_handler
#define arginfo_get_declared_classes arginfo_func_get_args
#define arginfo_get_declared_traits arginfo_func_get_args
@@ -272,8 +277,10 @@ ZEND_FUNCTION(get_included_files);
ZEND_FUNCTION(trigger_error);
ZEND_FUNCTION(set_error_handler);
ZEND_FUNCTION(restore_error_handler);
ZEND_FUNCTION(get_error_handler);
ZEND_FUNCTION(set_exception_handler);
ZEND_FUNCTION(restore_exception_handler);
ZEND_FUNCTION(get_exception_handler);
ZEND_FUNCTION(get_declared_classes);
ZEND_FUNCTION(get_declared_traits);
ZEND_FUNCTION(get_declared_interfaces);
@@ -336,8 +343,10 @@ static const zend_function_entry ext_functions[] = {
ZEND_RAW_FENTRY("user_error", zif_trigger_error, arginfo_user_error, 0, NULL, NULL)
ZEND_FE(set_error_handler, arginfo_set_error_handler)
ZEND_FE(restore_error_handler, arginfo_restore_error_handler)
ZEND_FE(get_error_handler, arginfo_get_error_handler)
ZEND_FE(set_exception_handler, arginfo_set_exception_handler)
ZEND_FE(restore_exception_handler, arginfo_restore_exception_handler)
ZEND_FE(get_exception_handler, arginfo_get_exception_handler)
ZEND_FE(get_declared_classes, arginfo_get_declared_classes)
ZEND_FE(get_declared_traits, arginfo_get_declared_traits)
ZEND_FE(get_declared_interfaces, arginfo_get_declared_interfaces)