- var_dump: documentation ( source)
- debug_backtrace: documentation ( source)
- array_shift: documentation ( source)
<?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();