2012-01-28 13 views
14

he vuelto a trabajar solo mi algoritmo de detección de recursividad en mi mascota dump_r proyecto()detectando recursión de matriz infinita en PHP?

https://github.com/leeoniya/dump_r.php

detectar la recursividad objeto no es demasiado difícil - se utiliza spl_object_hash() para obtener el identificador interno único de la instancia de objeto , almacénelo en un dict y compárelo contra él mientras descarga otros nodos.

para la detección por red de recursividad, yo soy un poco desconcertado, no he encontrado nada útil. php en sí mismo es capaz de identificar la recursión, aunque parece hacerlo un ciclo demasiado tarde. EDIT: NVM, que se produce cuando se necesita :)

$arr = array(); 
$arr[] = array(&$arr); 
print_r($arr); 

tiene que recurrir a hacer el seguimiento de todo en la pila de recursión y hacer comparaciones superficiales contra cualquier otro elemento de la matriz?

cualquier ayuda sería apreciada,
gracias!

+0

lol - eeewwwww. – leeoniya

+1

No es una respuesta a su pregunta, pero he visto soluciones que prueban 'print_r ($ var, true)' para la cadena que indica recursividad. Esto es lo peor que puedes conseguir pero funciona ... Ver [aquí] (http://noteslog.com/post/detecting-recursive-dependencies-in-php-composite-values/) para un compromiso decente. – Basic

+0

He eliminado/editado mi comentario para contener un enlace a un ejemplo, pero estoy de acuerdo, apesta – Basic

Respuesta

9

Debido mecanismo de llamada por valor de PHP, la única solución que veo aquí es iterar la matriz por referencia, y establecer un valor arbitrario en él, que le después comprobar si existe para averiguar si estaban allí antes:

function iterate_array(&$arr){ 

    if(!is_array($arr)){ 
    print $arr; 
    return; 
    } 

    // if this key is present, it means you already walked this array 
    if(isset($arr['__been_here'])){ 
    print 'RECURSION'; 
    return; 
    } 

    $arr['__been_here'] = true; 

    foreach($arr as $key => &$value){ 

    // print your values here, or do your stuff 
    if($key !== '__been_here'){ 
     if(is_array($value)){ 
     iterate_array($value); 
     } 

     print $value; 
    } 
    } 

    // you need to unset it when done because you're working with a reference... 
    unset($arr['__been_here']); 

} 

se podría concluir esta función a otra función que acepta valores en lugar de referencias, pero entonces tendría que recibir el aviso RECURSION desde el segundo nivel sobre. Creo que print_r hace lo mismo también.

+0

** esta ** es la solución que esperaba: simple e impresionante. – leeoniya

3

Alguien me va a corregir si estoy equivocado, pero PHP realmente está detectando la recursión en el momento correcto. Tu asignación simplemente crea el ciclo adicional. El ejemplo debe ser:

$arr = array(); 
$arr = array(&$arr); 

que se traducirá en

array(1) { [0]=> &array(1) { [0]=> *RECURSION* } } 

Tal como se esperaba.


Bueno, tengo un poco de curiosidad de cómo detectar la recursión y comencé a Google. He encontrado este artículo http://noteslog.com/post/detecting-recursive-dependencies-in-php-composite-values/ y esta solución:

function hasRecursiveDependency($value) 
{ 
    //if PHP detects recursion in a $value, then a printed $value 
    //will contain at least one match for the pattern /\*RECURSION\*/ 
    $printed = print_r($value, true); 
    $recursionMetaUser = preg_match_all('@\*RECURSION\*@', $printed, $matches); 
    if ($recursionMetaUser == 0) 
    { 
     return false; 
    } 
    //if PHP detects recursion in a $value, then a serialized $value 
    //will contain matches for the pattern /\*RECURSION\*/ never because 
    //of metadata of the serialized $value, but only because of user data 
    $serialized = serialize($value); 
    $recursionUser = preg_match_all('@\*RECURSION\*@', $serialized, $matches); 
    //all the matches that are user data instead of metadata of the 
    //printed $value must be ignored 
    $result = $recursionMetaUser > $recursionUser; 
    return $result; 
} 
+0

tiene razón. no es tarde pero todavía necesito una forma de hacer esto fuera de la función nativa. – leeoniya

+0

bueno, esta solución no es exactamente lo que esperaba, ya que es enormemente exigente en estructuras grandes y se basa en una profundidad de impresión interna incontrolable print_r() o serialización, que es parte de la razón por la que comencé el proyecto, je. , pero http://www.phpsadness.com/ :( – leeoniya

Cuestiones relacionadas