Category
Language · php-src-strict · magic method visibility (regression vs #146)
Problem
Zend: calling a private method from a scope that cannot see it is treated as “method not found” for that scope, so __call runs. The VM raises Error: Call to private method … from global scope and never enters __call.
| Repro (2026-07-31) |
Zend 8.2 |
VM |
$a->hid() with private function hid() + __call |
CALL_hid / m |
Error: Call to private method A::hid() from global scope |
php-src reference
PHP implementation target
lib/VM.php — method lookup / call frame setup (~__call dispatch ~16561+): when a method exists but visibility fails for the calling scope, fall through to __call with ($name, $arguments) (see existing MagicCallArgs) instead of throwing private-access Error
- Do not add C runtime branches
- Compliance:
test/compliance/cases/language/magic_call_private.phpt
Repro
./script/docker-exec.sh -- bash -lc 'cat > /tmp/call_priv.php <<'"'"'PHP'"'"'
<?php
class A {
private function hid() { return "p"; }
public function __call($n, $a) { echo "CALL_$n\n"; return "m"; }
}
$a = new A();
echo $a->hid(), "\n";
PHP
php bin/vm.php /tmp/call_priv.php'
Done when
Category
Language· php-src-strict · magic method visibility (regression vs #146)Problem
Zend: calling a private method from a scope that cannot see it is treated as “method not found” for that scope, so
__callruns. The VM raisesError: Call to private method … from global scopeand never enters__call.$a->hid()withprivate function hid()+__callCALL_hid/mError: Call to private method A::hid() from global scopephp-src reference
Zend/zend_object_handlers.c—zend_std_get_method/ call path: inaccessible method →__call__callbaseline)PHP implementation target
lib/VM.php— method lookup / call frame setup (~__calldispatch ~16561+): when a method exists but visibility fails for the calling scope, fall through to__callwith($name, $arguments)(see existingMagicCallArgs) instead of throwing private-accessErrortest/compliance/cases/language/magic_call_private.phptRepro
Done when
__callwith Zend args packing__call)