Как известно, в PHP не существует понятия вложенных контекстов. То есть, находясь внутри функции, невозможно получить родительский контекст. Это приводит, например, к тому, что переменные контекста не видны в замыканиях, хотя это и исправляется при помощи ключевого слова use. И если с замыканиями всё более или менее очевидно, то получить родительский контекст, отличный от глобального, возможно только если имеется парадигма вложенных контекстов. Так как в PHP она отсутствует, то я написал реализацию этого механизма.
На деле, ничего хорошего такой подход не сулит - как правило, нет необходимости обращаться к родительским контекстам. Тем не менее, возможность работать внутри замыканий с контекстом родителя кажется естественной. Ниже привожу код класса, который может реализовать эту функциональность:
PHP:
скопировать код в буфер обмена
скопировать код в буфер обмена
- class Scope
- {
- const SCOPE_TYPE_PARENT = 2;
- const SCOPE_TYPE_SELF = 1;
- protected static $_rInstance = null;
- public static function getInstance()
- {
- if(!self::$_rInstance)
- {
- self::$_rInstance = new self;
- }
- return self::$_rInstance;
- }
- public function getScope($iLevel = self::SCOPE_TYPE_PARENT)
- {
- if(!($rgCaller = $rgTrace[$iLevel]))
- {
- return null;//TODO
- }
- $rContainer = array_key_exists('class', $rgCaller)?new ReflectionMethod($rgCaller['class'], $rgCaller['function']):new ReflectionFunction($rgCaller['function']);
- foreach($rContainer->getParameters() as $iIndex=>$rReflection)
- {
- $rgParameters[$rReflection->name] = isset($rgCaller['args'][$iIndex])?$rgCaller['args'][$iIndex]:null;
- }
- {'.'extract($rgParameters);'.
- PHP_EOL.trim(join('',array_slice(file(__FILE__), $rContainer->getStartLine(), $rgTrace[$iLevel-1]['line']-$rContainer->getStartLine()-1)),"\n\r {").';'.
- PHP_EOL.'return get_defined_vars();'.
- PHP_EOL.'};');
- {
- $fnParent = $fnParent->bindTo($rgCaller['object'], $rgCaller['class']);
- }
- return array_merge($rgParameters, array_diff_key($fnParent($rgParameters), ['rgParameters'=>null]));
- }
- }