<?php
function get_calling_scope() {
$trace = debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT);
array_shift($trace); // Remove current frame
$frame = array_shift($trace);
if ($frame === null) {
return null;
}
$function = $frame['function'];
if (!in_array($function, ['__get', '__set', '__isset', '__unset', '__call', '__callStatic'], true)) {
return null;
}
$object = $frame['object'] ?? null;
$property = $frame['args'][0];
foreach ($trace as $previousFrame) {
$previousObject = $previousFrame['object'] ?? null;
if ($previousFrame['function'] !== $function
|| $previousObject !== $object
|| $previousFrame['args'][0] !== $property) {
return $previousObject !== null
? $previousObject::class
: null;
}
}
return null;
}
class Foo {
public function __get($name) {
var_dump(get_calling_scope());
return '';
}
public function test() {
$this->bar;
}
}
class Bar extends Foo {
public function __get($name) {
parent::__get($name);
return '';
}
}
$foo = new Foo();
$foo->bar;
$foo->test();
$bar = new Bar();
$bar->test();
- Output for 8.0.1 - 8.0.30, 8.1.0 - 8.1.33, 8.2.0 - 8.2.29, 8.3.0 - 8.3.25, 8.4.1 - 8.4.12
- NULL
string(3) "Foo"
string(3) "Bar"
preferences:
93.84 ms | 406 KiB | 5 Q