Skip to content

Commit c05a85d

Browse files
committed
zend_get_callable_name: Return underlying callable’s name for fake closures
Fixes #18062
1 parent a7d2703 commit c05a85d

File tree

2 files changed

+45
-0
lines changed

2 files changed

+45
-0
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
--TEST--
2+
First Class Callable returns correct name from is_callable()
3+
--FILE--
4+
<?php
5+
6+
class Foo {
7+
public function __invoke() {
8+
9+
}
10+
11+
public static function bar() {
12+
13+
}
14+
}
15+
16+
function some_func() {
17+
18+
}
19+
20+
is_callable(some_func(...), callable_name: $name);
21+
var_dump($name);
22+
23+
is_callable((new Foo())(...), callable_name: $name);
24+
var_dump($name);
25+
26+
is_callable(Foo::bar(...), callable_name: $name);
27+
var_dump($name);
28+
?>
29+
--EXPECT--
30+
string(17) "Closure::__invoke"
31+
string(17) "Closure::__invoke"
32+
string(17) "Closure::__invoke"

Zend/zend_API.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3972,6 +3972,19 @@ ZEND_API zend_string *zend_get_callable_name_ex(zval *callable, zend_object *obj
39723972
case IS_OBJECT:
39733973
{
39743974
zend_class_entry *ce = Z_OBJCE_P(callable);
3975+
3976+
if (ce == zend_ce_closure) {
3977+
const zend_function *fn = zend_get_closure_method_def(Z_OBJ_P(callable));
3978+
3979+
if (fn->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) {
3980+
if (fn->common.scope) {
3981+
return zend_create_member_string(fn->common.scope->name, fn->common.function_name);
3982+
} else {
3983+
return zend_string_copy(fn->common.function_name);
3984+
}
3985+
}
3986+
}
3987+
39753988
return zend_string_concat2(
39763989
ZSTR_VAL(ce->name), ZSTR_LEN(ce->name),
39773990
"::__invoke", sizeof("::__invoke") - 1);

0 commit comments

Comments
 (0)