Ale*_*lex 3 php variables global-variables
我知道变量名称$var和它的值.
如果我检查isset($GLOBALS[$var_name]) && $GLOBALS[$var_name] == $var我可能得到一个肯定的结果,即使变量不是真正的全局,但碰巧与现有的全局变量具有相同的名称和值:(
我需要这个用于我正在构建的调试功能,以显示有关传递的变量类型的更多信息.
我还可以找出变量是否是静态的吗?:)
ps:反射对我没有帮助..它只能获取对象或函数的信息......
如果变量是彼此的引用(基本上是您要检查的),它们将使用相同的zval.因此,这是一个有点令人讨厌,但将会工作的方式:
<?php
function vars_are_referenced (&$var1, &$var2) {
// What we are doing *will* throw an error (I said it was nasty ;-) )
$oldER = error_reporting();
$oldDE = ini_get('display_errors');
error_reporting(0);
ini_set('display_errors', 0);
// We need to use output buffering, we don't want to break any existing
// buffering so we cache the contents of the buffer
$oldBuffer = ob_get_length() ? ob_get_clean() : NULL;
// If the values are not identical, definitely not a match
if ($var1 !== $var2) return FALSE;
// Now we inspect the zval of $var1
ob_start();
debug_zval_dump(&$var1);
preg_match('/\brefcount\((\d+)\)(?:\b|$)/', ob_get_clean(), $matches);
$var1RefCountBefore = (int) $matches[1];
// If they are the same, this will increase the refcount
$temp = &$var2;
// Inspect the zval of $var1 again
ob_start();
debug_zval_dump(&$var1);
preg_match('/\brefcount\((\d+)\)(?:\b|$)/', ob_get_clean(), $matches);
$var1RefCountAfter = (int) $matches[1];
// If refcount is now greater, they are the same
$result = $var1RefCountAfter > $var1RefCountBefore;
// Repopulate the output buffer if necessary
if ($oldBuffer !== NULL) {
ob_start();
echo $oldBuffer;
}
// Turn error reporting back to correct level
error_reporting($oldER);
ini_set('display_errors', $oldDE);
return $result;
}
function test_ref_fail () {
$a = 1;
$var_name = 'a';
var_dump(vars_are_referenced($GLOBALS['a'], $a));
}
function test_ref_success_1 () {
global $a;
$var_name = 'a';
var_dump(vars_are_referenced($GLOBALS['a'], $a));
}
function test_ref_success_2 (&$a) {
$var_name = 'a';
var_dump(vars_are_referenced($GLOBALS['a'], $a));
}
$a = 1;
$b = &$a;
var_dump(vars_are_referenced($a, $b));
test_ref_fail();
test_ref_success_1();
test_ref_success_2($a);
Run Code Online (Sandbox Code Playgroud)
这是最好的方法(通过检查zval),但是我确信你可以看到,这对于PHP当前可用的函数来说不是一个漂亮的方法.它会引发错误,因为调用时间传递引用是debug_zval_dump()我们需要的工作所必需的.它将导致PHP> = 5.4中的致命错误,因为已删除了调用时传递引用.
因此,这里是另一种方式来做到这一点-我不喜欢,因为它涉及到修改的变量,但它不应该打破任何东西,重要的是,不会引发任何错误,将工作无处不在:
<?php
function vars_are_referenced (&$var1, &$var2) {
// If the values are not identical, definitely not a match
if ($var1 !== $var2) return FALSE;
// Make a copy of the old value
$oldVal = $var1;
// Get a new value we can assign that is different to the old value
$newVal = ($oldVal === 1) ? 2 : 1;
// Assign the value to $var1
$var1 = $newVal;
// See if $var2 has changed
$result = $var1 === $var2;
// Put the value of $var1 right again
$var1 = $oldVal;
return $result;
}
Run Code Online (Sandbox Code Playgroud)
这是一个辅助函数(可以与vars_are_referenced()上面的任何一个定义一起使用),根据作为字符串的变量名称和变量本身,具体确定变量是否为全局变量:
<?php
function var_is_global ($name, &$var) {
return vars_are_referenced($GLOBALS[$name], $var);
}
Run Code Online (Sandbox Code Playgroud)
我想不出一种方法可以准确地检查任意变量是否在对象的上下文之外是静态的.