Возьмите пик при xdebug_debug_zval(). Прямо сейчас, это единственный способ узнать, можете ли вы определить все о zval переменной.
Так вот несколько вспомогательных функций, чтобы определить некоторую полезную информацию:
function isRef($var) {
$info = getZvalRefCountInfo($var);
return (boolean) $info['is_ref'];
}
function getRefCount($var) {
$info = getZvalRefCountInfo($var);
return $info['refcount'];
}
function canCopyOnWrite($var) {
$info = getZvalRefCountInfo($var);
return $info['is_ref'] == 0;
}
function canReferenceWithoutCopy($var) {
$info = getZvalRefCountInfo($var);
return $info['is_ref'] == 1 || $info['refcount'] == 1;
}
function getZvalRefCountInfo($var) {
ob_start();
xdebug_debug_zval($var);
$info = ob_get_clean();
preg_match('(: \(refcount=(\d+), is_ref=(\d+)\))', $info, $match);
return array('refcount' => $match[1], 'is_ref' => $match[2]);
}
Так что с некоторыми переменными выборки:
$a = 'test';
$b = $a;
$c = $b;
$d =& $c;
$e = 'foo';
Мы можем проверить, является ли переменная ссылка:
isRef('a'); // false
isRef('c'); // true
isRef('e'); // false
Мы можем получить количество переменных, связанных с zval (не обязательно ссылку, может быть для копирования при записи):
getRefCount('a'); // 2
getRefCount('c'); // 2
getRefCount('e'); // 1
Мы можем проверить, можем ли мы копировать при записи (копия без выполнения копии памяти):
canCopyOnWrite('a'); // true
canCopyOnWrite('c'); // false
canCopyOnWrite('e'); // true
И мы можем проверить, если мы можем сделать ссылка без копирования ZVAL:
canReferenceWithoutCopy('a'); // false
canReferenceWithoutCopy('c'); // true
canReferenceWithoutCopy('e'); // true
И теперь мы можем проверить, является ли переменная ссылки себя через какой-то черной магии:
function isReferenceOf(&$a, &$b) {
if (!isRef('a') || getZvalRefCountInfo('a') != getZvalRefCountInfo('b')) {
return false;
}
$tmp = $a;
if (is_object($a) || is_array($a)) {
$a = 'test';
$ret = $b === 'test';
$a = $tmp;
} else {
$a = array();
$ret = $b === array();
$a = $tmp;
}
return $tmp;
}
Это немного хакерство, так как мы не можем определить, какие другие символы ссылаются на один и тот же zval (только эта ссылка на другие символы). Таким образом, это в основном проверяет, является ли $a
ссылкой, и если $a
и $b
оба имеют одинаковый набор ссылок и набор опорных флагов. Затем он меняет один, чтобы проверить, изменилась ли другая (указывая, что они являются одной и той же ссылкой).
Вы можете проверить, если две переменные ссылки друг друга: http://stackoverflow.com/a/18110347/632951 – Pacerier