2010-06-30 9 views
15

Lamento preguntar, es tarde y no puedo encontrar la forma de hacerlo ... ¿alguien puede ayudar?PHP: compruebe si object/array es una referencia

$users = array(
    array(
     "name" => "John", 
     "age" => "20" 
    ), 
    array(
     "name" => "Betty", 
     "age" => "22" 
    ) 
); 

$room = array(
    "furniture" => array("table","bed","chair"), 
    "objects" => array("tv","radio","book","lamp"), 
    "users" => &$users 
); 

var_dump $ sala de muestra:

... 
'users' => & 
... 

que significa "usuarios" es una referencia.

me gustaría hacer algo como esto:

foreach($room as $key => $val) { 
    if(is_reference($val)) unset($room[$key]); 
} 

El objetivo principal consiste en copiar la matriz sin ninguna referencia.

¿Es esto posible?

Gracias.

+2

El primer comentario se muestra cómo se puede hacer: http://www.php.net/manual /es/language.references.spot.php – pritaeas

+0

Quieres $ habitación sin la clave de usuario, ¿verdad? ¿Puede haber otras referencias o solo serían usuarios? – Gordon

+0

Sí. El problema es que tengo una matriz de gran tamaño con muchas referencias cruzadas dentro de ella. Y quiero obtener una parte de ella, pero sin las referencias. En resumen, la clave puede ser variable. Ahora soy un poco flojo y no quiero rastrear todas las referencias actuales y futuras. – lepe

Respuesta

7

Puede comprobar las referencias en una matriz multidimensional haciendo una copia de la matriz, y luego alterar y probar cada entrada a su vez:

$roomCopy = $room; 
foreach ($room as $key => $val) { 
    $roomCopy[$key]['_test'] = true; 
    if (isset($room[$key]['_test'])) { 
    // It's a reference 
    unset($room[$key]); 
    } 
} 
unset($roomCopy); 

Con los datos del ejemplo, $room['furniture'] y $roomCopy['furniture'] será matrices separadas (como $roomCopy es una copia de $room), por lo que agregar una nueva clave a una no afectará a la otra. Pero, $room['users'] y $roomCopy['users'] serán referencias a la misma matriz $users (ya que es la referencia que se copia, no la matriz), de modo que cuando agreguemos una clave a $roomCopy['users'], se muestre en $room['users'].

+1

Tipo de solución sucia pero creativa ... +1 – lepe

+1

Analizando el enlace dado por pritaeas, resulta ser casi la misma solución que esta pero más extendida (aún prefiero esta compilación reducida). – lepe

1

algo recursivo tal vez.

function removeReferences($inbound) 
{ 
    foreach($inbound as $key => $context) 
    { 
     if(is_array($context)) 
     { 
      $inbound[$key] = removeReferences($context) 
     }elseif(is_object($context) && is_reference($context)) 
     { 
      unset($inbound[$key]); //Remove the entity from the array. 
     } 
    } 
    return $inbound; 
} 
+4

Excepto 'is_reference' no existe. Eso es lo que persigue;) – Chris

+0

sí, mal, publiqué eso y me di cuenta de que intenté encontrar una solución, pero el método sucio de Chris Smith parece ser el único – RobertPitt

3

Lo mejor que puede hacer es una prueba de dos variables para determinar si se trata de una referencia al otro:

$x = "something"; 
$y = &$x; 
$z = "something else"; 

function testReference(&$xVal,&$yVal) { 
    $temp = $xVal; 
    $xVal = "I am a reference"; 
    if ($yVal == "I am a reference") { echo "is reference<br />"; } else { echo "is not reference<br />"; } 
    $xVal = $temp; 
} 

testReference($x,$y); 
testReference($y,$x); 

testReference($x,$z); 
testReference($z,$x); 

testReference($y,$z); 
testReference($z,$y); 

pero dudo si es de mucha ayuda

método muy sucio (Tampoco se ha probado bien):

$x = "something"; 
$y = &$x; 
$z = "something else"; 

function isReference(&$xVal) { 
    ob_start(); 
    debug_zval_dump(&$xVal); 
    $dump = ob_get_clean(); 
    preg_match('/refcount\((\d*)\)/',$dump,$matches); 
    if ($matches[1] > 4) { return true; } else { return false; } 
} 

var_dump(isReference($x)); 
var_dump(isReference($y)); 
var_dump(isReference($z)); 

Para utilizar este último método en su código, necesitaría hacer algunas cosa como:

foreach($room as $key => $val) { 
    if(isReference($room[$key])) unset($room[$key]); 
} 

porque $ val nunca es una referencia, ya que es una copia del elemento de matriz original; y el uso de & $ val hace que sea siempre una referencia

+0

. Para los valores simples (cadena, int, etc.) tu primer método podría funcionar (como es básicamente lo que Chris publicó), pero no para las matrices. El segundo método es interesante el uso de debug_zval_dump "refcount". Pero en mi humilde opinión sería casi lo mismo que analizar el resultado "y" del resultado var_dump, con la diferencia de que con este método es posible obtener el número de referencias. Por cierto, pasar referencias, como argumento, a las funciones está en desuso. Debería ser: debug_zval_dump ($ xVal); – lepe

+0

debug_zval_dump() es bastante extraño en lo que respecta a pass-by-reference/pass-by-value, y hay un bloque completo en la documentación dedicada a ese tema. Sin embargo, a menos que use la forma obsoleta de pass-by-reference, debug_zval_dump() parece funcionar en una copia (con un refcount de 1) en lugar de la variable en sí ... es como un vestigio olvidado del antiguo método de pase -por referencia –

+0

Oh, ya veo. Interesante... – lepe

1
function var_reference_count(&$xVal) { 
    $ao = is_array($xVal)||is_object($xVal); 

    if($ao) { $temp= $xVal; $xVal=array(); } 

    ob_start();   
    debug_zval_dump(&$xVal); 
    $dump = ob_get_clean(); 

    if($ao) $xVal=$temp; 

    preg_match('/refcount\((\d*)\)/',$dump,$matches); 
    return $matches[1] - 3; 
} 
//------------------------------------------------------------------------------------------- 

Esto funciona con objetos Hudge y matrices.

0

si usted quiere deshacerse de elementos recursivos:

<?php 
$arr=(object)(NULL); $arr->a=3; $arr->b=&$arr; 
//$arr=array('a'=>3, 'b'=>&$arr); 
print_r($arr); 

$arr_clean=eval('return '.strtr(var_export($arr, true), array('stdClass::__set_state'=>'(object)')).';'); 
print_r($arr_clean); 
?> 

de salida:

stdClass Object ([a] => 3 [b] => stdClass Object *RECURSION*) 
stdClass Object ([a] => 3 [b] =>) 
Cuestiones relacionadas