Haz un pico en xdebug_debug_zval(). En este momento, esa es la única manera de saber realmente si puedes determinar todo sobre el zval de la variable.
Así que aquí hay un par de funciones de ayuda para determinar alguna información útil:
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]);
}
Así, con algunas variables de la muestra:
$a = 'test';
$b = $a;
$c = $b;
$d =& $c;
$e = 'foo';
podemos probar si una variable es una referencia:
isRef('a'); // false
isRef('c'); // true
isRef('e'); // false
Podemos obtener el número de variables relacionadas con el zval (no necesariamente una referencia, puede ser para la copia en escritura):
getRefCount('a'); // 2
getRefCount('c'); // 2
getRefCount('e'); // 1
podemos probar si podemos copiar al escribir (copiar sin realizar una copia de la memoria):
canCopyOnWrite('a'); // true
canCopyOnWrite('c'); // false
canCopyOnWrite('e'); // true
Y podemos probar si podemos hacer una referencia sin copiar el zval:
canReferenceWithoutCopy('a'); // false
canReferenceWithoutCopy('c'); // true
canReferenceWithoutCopy('e'); // true
Y ahora, podemos comprobar si una variable referencia a sí mismo a través de un poco de magia negro:
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;
}
Es un poco hacky ya que no podemos determinar qué otros símbolos hacen referencia al mismo zval (solo esa otra referencia de símbolos). Así que esto básicamente verifica si $a
es una referencia, y si $a
y $b
tienen el mismo refcount y conjunto de banderas de referencia. Luego, cambia uno para verificar si el otro cambia (lo que indica que son la misma referencia).
se puede comprobar si dos variables son referencias de uno al otro: http://stackoverflow.com/a/18110347/632951 – Pacerier